使用本地库(C而已,没有C ++),并没有发现实施 [英] Using native lib (C only, no C++), and No Implementation Found

查看:285
本文介绍了使用本地库(C而已,没有C ++),并没有发现实施的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用这个LIB

试图在Android上巨著和AFAIK,链接和期待的.so好。

错误的调用C函数(我也跟着这些intstructs 的)

  D / OpusRecorder(1964):开始录制!
E /艺术(1964年):未找到INT com.droidkit.opus.OpusLib.startRecord(java.lang.String中)实现(试过Java_com_droidkit_opus_OpusLib_startRecord和Java_com_droidkit_opus_OpusLib_startRecord__Ljava_lang_String_2)
E / AndroidRuntime(1964):致命异常:螺纹8227
E / AndroidRuntime(1964):工艺:com.borneo.speech,PID:1964
E / AndroidRuntime(1964):java.lang.UnsatisfiedLinkError中:未找到INT com.droidkit.opus.OpusLib.startRecord(java.lang.String中)实现(试过Java_com_droidkit_opus_OpusLib_startRecord和Java_com_droidkit_opus_OpusLib_startRecord__Ljava_lang_String_2)
E / AndroidRuntime(1964):在com.droidkit.opus.OpusLib.startRecord(本机方法)
E / AndroidRuntime(1964年):在com.borneo.speech.OpusRecorder.run(OpusRecorder.java:439)
W / ActivityManager(724):强制完成活动1 com.borneo.speech / .Speech_API_Activity

中的.so打包在APK

功能与类型=T...

中的.so存在

  AAR $纳米-D libopus.so |头
000084c1ŧJava_com_droidkit_opus_OpusLib_closeOpusFile
000084c5ŧJava_com_droidkit_opus_OpusLib_isOpusFile
00008491ŧJava_com_droidkit_opus_OpusLib_openOpusFile
00008471ŧJava_com_droidkit_opus_OpusLib_readOpusFile
00008489ŧJava_com_droidkit_opus_OpusLib_seekOpusFile
00008145ŧJava_com_droidkit_opus_OpusLib_startRecord ***

---铛细节---

在C实现的:

audio.c

 的#includecom_droidkit_opus_OpusLib.h<  - 从Java类= com.droidkit.opus.OpusLib通过JAVAH

//转每贝罗@Nicklas

  JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord(JNIEnv的* ENV,jobject javaThis,路径的jstring){
    为const char * pathStr =(* ENV) - GT; GetStringUTFChars(ENV,路径,0);    INT结果= initRecorder(pathStr);    如果(pathStr!= 0){
        (* ENV) - GT; ReleaseStringUTFChars(ENV,路径,pathStr);
    }    返回结果;
}

C头...

  / * DO NOT EDIT这个文件 - 它是生成的机器* /
#包括LT&;&jni.h GT;
/ *头类com_droidkit_opus_OpusLib * /的#ifndef _Included_com_droidkit_opus_OpusLib
#定义_Included_com_droidkit_opus_OpusLib
#IFDEF __cplusplus
为externC{
#万一
/ *
 *类别:com_droidkit_opus_OpusLib
 *方法:startRecord用于
 *签名:(Ljava /朗/字符串;)我
 * /
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord
  (JNIEnv的*,jobject,的jstring);/ *
 *类别:com_droidkit_opus_OpusLib
 *方法:writeFrame
 *签名:(Ljava / NIO / ByteBuffer的;我)我
 * /
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_writeFrame
  (JNIEnv的*,jobject,jobject,jint);/ *
 *类别:com_droidkit_opus_OpusLib
 *方法:STO precord
 *签名:()V
 * /
JNIEXPORT无效JNICALL Java_com_droidkit_opus_OpusLib_sto precord
  (JNIEnv的*,jobject);/ *
 *类别:com_droidkit_opus_OpusLib
 *方法:isOpusFile
 *签名:(Ljava /朗/字符串;)我
 * /
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_isOpusFile
  (JNIEnv的*,jobject,的jstring);...
#IFDEF __cplusplus
}
#万一
#万一

=== JAVA详细呼吁为C ===

== == EDITED Java本地申报。

  / **
 * OpusLib结合本土
 * /
公共类OpusLib {    静态的 {
        的System.loadLibrary(作品);
    }    / **
     *启动OPUS记录
     *
     * @参数路径文件路径
     * @返回非零如果玩家开始
     * /
    公共本土INT startRecord用于(字符串路径);
    / **
     *写作音频帧EN codeR
     *
     *有声在16位单声道PCM格式16000 @参数帧缓冲
     * @参数LEN LEN数据
     返回:不为空,如果成功
     * /
    公共本土INT writeFrame(ByteBuffer的框架,INT LEN);    / **
     *停车记录
     * /
    公共本土无效STO precord();    / **
     *检查作品文件格式
     *
     * @参数路径文件路径
     * @返回非零如果OPUS文件
     * /
    公共本土INT isOpusFile(字符串路径);    / **
     *打开文件
     *
     * @参数路径文件路径
     * @返回非零如果成功
     * /
    公共本土INT openOpusFile(字符串路径);    / **
     *在OPUS文件求
     *
     *文件@param位置的位置
     * @返回非零如果成功
     * /
    公共本土INT seekOpusFile(浮动位);    / **
     *截止OPUS文件
     * /
    公共本土无效closeOpusFile();    / **
     *从OPUS文件中读取
     *
     * @参数缓冲区
     * @参数容量
     * /
    公共本土无效readOpusFile(ByteBuffer的缓冲区,诠释能力);    / **
     *是否播放完毕
     *
     * @返回非零如果回放结束
     * /
    公共本土INT getFinished();    / **
     *在readOpusFile读取的块大小
     *
     以字节为单位* @返回块大小
     * /
    公共本土INT的getSize();    / **
     *偏移实际的声音回放的
     *
     * @返回偏移
     * /
    公共天然长getPcmOffset();    / **
     *总OPUS PCM时间
     *
     * @返回PCM时间
     * /
    公共天然长getTotalPcmDuration();}        尝试{
            OPUS =新OpusLib();
        }赶上(ULX的UnsatisfiedLinkError){
            Log.e(LTAG,非法机负载:+ ulx.getMessage());
        }...
公共类OpusLib {
    静态的 {
        的System.loadLibrary(作品);
    }

据我所知,LIB是越来越加载确定

UnsatisfiedLink EXCP下面最后一行出现

私有String =的mpath路径;

 如果(mShouldRecord)
       INT薄荷= opus.startRecord(的mpath); < - 抛出unsatisfiedLink - 没有发现实施

startRecord用于在符号表本书虽然我不是一定所有的功能PARM的类型匹配起来?看到STRING_2...

startRecord__Ljava_lang_String_2)

====构建信息摇篮和linkedit ===

 链接:
命令:/ usr / local / src目录/ Android的NDK-r10d / NDK的构建NDK_PROJECT_PATH = NULL APP_BUILD_SCRIPT=/home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/Android.mk APP_PLATFORM = Android的19 NDK_OUT = /家庭/抢劫/ src目录的/ tmp / speechnw /库/ OPUS /编译/中间体/ NDK /发行/ OBJ NDK_LIBS_OUT = /家庭/抢劫/ src目录的/ tmp / speechnw /库/ OPUS /编译/中间体/ NDK /发行/ lib目录APP_STL = stlport_static APP_ABI = armeabi,V7A[armeabi-V7A]编译大拇指:OPUS< = audio.c
...
[armeabi-V7A] SharedLibrary:libopus.so
[armeabi-V7A]安装:libopus.so => /home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/lib/armeabi-v7a/libopus.so

的build.gradle

defaultConfig {
    8的minSdkVersion
    targetSdkVersion 19
    版本code 1
    的versionName1.1.1

  NDK {
    MODULENAME巨著    CFLAGS-DANDROID_NDK+
            -DDISABLE_IMPORTGL+
            -w -std = gnu99 -O3 -fno严格走样-f prefetch环阵列+
            -DNULL = 0 -DSOCKLEN_T = socklen_t的-DLOCALE_NOT_USED -D_LARGEFILE_SOURCE = 1 -D_FILE_OFFSET_BITS = 64+
            -Drestrict =''-D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-数学错误号
            -DAVOID_TABLES
    LDLIBS日志,m的
    STLstlport_static
    abiFilterarmeabi-V7A
}

}


解决方案

替换此行:

  JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord(JNIEnv的* ENV,JCLASS类的jstring路径){

  JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord(JNIEnv的* ENV,jobject javaThis,路径的jstring){

您已经用C映射定义Java中的静态方法,但在Java你使用它作为一个实例方法的功能。我把它换成是这样的: JCLASS类, jobject javaThis,在你的C函数签名。另请注意,在你的C头你还宣布与实例方法签名的功能,只是因为它似乎你打算。

tried using this lib for opus on android and AFAIK, the link and the .so look to be good.

ERROR on call to C function ( i followed these intstructs )

D/OpusRecorder( 1964): Start recording!
E/art     ( 1964): No implementation found for int com.droidkit.opus.OpusLib.startRecord(java.lang.String) (tried Java_com_droidkit_opus_OpusLib_startRecord and Java_com_droidkit_opus_OpusLib_startRecord__Ljava_lang_String_2)
E/AndroidRuntime( 1964): FATAL EXCEPTION: Thread-8227
E/AndroidRuntime( 1964): Process: com.borneo.speech, PID: 1964
E/AndroidRuntime( 1964): java.lang.UnsatisfiedLinkError: No implementation found for int com.droidkit.opus.OpusLib.startRecord(java.lang.String) (tried Java_com_droidkit_opus_OpusLib_startRecord and Java_com_droidkit_opus_OpusLib_startRecord__Ljava_lang_String_2)
E/AndroidRuntime( 1964):    at com.droidkit.opus.OpusLib.startRecord(Native Method)
E/AndroidRuntime( 1964):    at com.borneo.speech.OpusRecorder.run(OpusRecorder.java:439)
W/ActivityManager(  724):   Force finishing activity 1 com.borneo.speech/.Speech_API_Activity

The .so is packaged in apk

function exist in the .so with Type= "T"...

aar$ nm -D libopus.so | head
000084c1 T Java_com_droidkit_opus_OpusLib_closeOpusFile
000084c5 T Java_com_droidkit_opus_OpusLib_isOpusFile
00008491 T Java_com_droidkit_opus_OpusLib_openOpusFile
00008471 T Java_com_droidkit_opus_OpusLib_readOpusFile
00008489 T Java_com_droidkit_opus_OpusLib_seekOpusFile
00008145 T Java_com_droidkit_opus_OpusLib_startRecord ***

---CLang details---

implementation in C:

audio.c

#include "com_droidkit_opus_OpusLib.h"   <-- from the Java class=com.droidkit.opus.OpusLib via javah

//rev belo per @Nicklas

JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord(JNIEnv *env, jobject javaThis, jstring path) {
    const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);

    int result = initRecorder(pathStr);

    if (pathStr != 0) {
        (*env)->ReleaseStringUTFChars(env, path, pathStr);
    }

    return result;
}

c headers...

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_droidkit_opus_OpusLib */

#ifndef _Included_com_droidkit_opus_OpusLib
#define _Included_com_droidkit_opus_OpusLib
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_droidkit_opus_OpusLib
 * Method:    startRecord
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord
  (JNIEnv *, jobject, jstring);

/*
 * Class:     com_droidkit_opus_OpusLib
 * Method:    writeFrame
 * Signature: (Ljava/nio/ByteBuffer;I)I
 */
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_writeFrame
  (JNIEnv *, jobject, jobject, jint);

/*
 * Class:     com_droidkit_opus_OpusLib
 * Method:    stopRecord
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_droidkit_opus_OpusLib_stopRecord
  (JNIEnv *, jobject);

/*
 * Class:     com_droidkit_opus_OpusLib
 * Method:    isOpusFile
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_isOpusFile
  (JNIEnv *, jobject, jstring);

...
#ifdef __cplusplus
}
#endif
#endif

===JAVA Details Calls to C===

==EDITED== Java Native Decl.

/**
 * OpusLib native binding
 */
public class OpusLib {

    static {
        System.loadLibrary("opus");
    }

    /**
     * Starting opus recording
     *
     * @param path path to file
     * @return non zero if started player
     */
    public native int startRecord(String path);


    /**
     * Writing audio frame to encoder
     *
     * @param frame buffer with sound in 16 bit mono PCM 16000 format
     * @param len   len of data
     * @return not null if successful
     */
    public native int writeFrame(ByteBuffer frame, int len);

    /**
     * Stopping record
     */
    public native void stopRecord();

    /**
     * Checking Opus File format
     *
     * @param path path to file
     * @return non zero if opus file
     */
    public native int isOpusFile(String path);

    /**
     * Opening file
     *
     * @param path path to file
     * @return non zero if successful
     */
    public native int openOpusFile(String path);

    /**
     * Seeking in opus file
     *
     * @param position position in file
     * @return non zero if successful
     */
    public native int seekOpusFile(float position);

    /**
     * Closing opus file
     */
    public native void closeOpusFile();

    /**
     * Reading from opus file
     *
     * @param buffer
     * @param capacity
     */
    public native void readOpusFile(ByteBuffer buffer, int capacity);

    /**
     * Is playback finished
     *
     * @return non zero if playback is finished
     */
    public native int getFinished();

    /**
     * Read block size in readOpusFile
     *
     * @return block size in bytes
     */
    public native int getSize();

    /**
     * Offset of actual sound for playback
     *
     * @return offset
     */
    public native long getPcmOffset();

    /**
     * Total opus pcm duration
     *
     * @return pcm duration
     */
    public native long getTotalPcmDuration();

}

        try {
            opus = new OpusLib();
        }catch(UnsatisfiedLinkError ulx) {
            Log.e(LTAG, "Illegal native Load: " + ulx.getMessage());
        }

...
public class OpusLib {
    static {
        System.loadLibrary("opus");
    }   

AFAIK , lib is getting loaded ok

UnsatisfiedLink Excp occurs on last line below:

private String mPath = path;

   if (mShouldRecord)            
       int mint = opus.startRecord(mPath);     <-- throws unsatisfiedLink - no implementation found   

startRecord is in the symbols table altho im not certain all the function parm types match up? see the "string_2"...

startRecord__Ljava_lang_String_2)

==== Build info Gradle and linkedit ===

link :
command: /usr/local/src/android-ndk-r10d/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/Android.mk APP_PLATFORM=android-19 NDK_OUT=/home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/obj NDK_LIBS_OUT=/home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/lib APP_STL=stlport_static APP_ABI=armeabi-v7a

[armeabi-v7a] Compile thumb  : opus <= audio.c                       
...
[armeabi-v7a] SharedLibrary  : libopus.so
[armeabi-v7a] Install        : libopus.so => /home/rob/src/tmp/speechnw/libraries/opus/build/intermediates/ndk/release/lib/armeabi-v7a/libopus.so

build.gradle

defaultConfig { minSdkVersion 8 targetSdkVersion 19 versionCode 1 versionName "1.1.1"

ndk {
    moduleName "opus"

    cFlags "-DANDROID_NDK " +
            "-DDISABLE_IMPORTGL " +
            "-w -std=gnu99 -O3 -fno-strict-aliasing -fprefetch-loop-arrays " +
            "-DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 "+
            "-Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno "
            "-DAVOID_TABLES "
    ldLibs "log", "m"
    stl "stlport_static"
    abiFilter "armeabi-v7a"
}

}

解决方案

Replace this line:

JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord(JNIEnv *env, jclass class, jstring path) {

with:

JNIEXPORT jint JNICALL Java_com_droidkit_opus_OpusLib_startRecord(JNIEnv *env, jobject javaThis, jstring path) {

The function you've defined in C maps to a static method in Java, but in Java you're using it as an instance method. What I've replaced is this: jclass class, with jobject javaThis, in your C function signature. Please also note that in your C headers you've also declared the functions with instance method signatures, just as it seems you're intending to.

这篇关于使用本地库(C而已,没有C ++),并没有发现实施的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆