我有一个库 libraryOne.so (File1.c),它包含纯 C 代码。 现在我想从我的 Java 文件访问这段代码。为此,我将使用标准的 JNI 过程。 但是为了使用 JNI,我还应该修改我的 File1.c 中的 C 代码(比如包括 JNI 的头文件和一些标准的 JNIEXPORT 东西)。 所以我正在创建一个包装器库(libraryWrapper.so 由 File2.c 制成)。 此库将包含所需的 JNI 声明并应与我的 Java 文件交互。 现在我想知道如何从 File2.c 调用 File1.c 的纯 C 函数
最佳答案
首先,您应该阅读 ndk-tutorial。因为你需要设置 ndk 等等。之后你可以寻找 ndk 示例来学习如何做事。以及如何构建
实际上上面就是你的答案。 来回答你的问题。
你应该有 libraryOne.so 的源代码。正如你所说的那样。因为android针对很多平台,你的so不能在上面运行。所以它需要用ndk编译
OK 让我们的文件 File1.c
int myfunction(const char* st){
int answer=0;
//stufs here
return answer;
}
首先,添加我们要访问的Java类
package example.com.myapplication;
public class JniClass {
static {
System.loadLibrary("libraryWrapper");
}
public native int myFunction(String a );
}
现在我们需要包装器。为此我们应该知道jni接口(interface)。幸运的是,有一个名为 javah 的工具可以为我们生成它,让我们不必为所有调用手动生成它。 我们应该构建我们的 android 项目,以便生成类文件。 我使用调试构建它,因此我生成的文件将位于此/app/build/intermediates/classes/debug 文件夹中。
好的,然后我们运行 javah
javah -jni example.com.myapplication.JniClas
s
如果您遇到错误,请参阅 Javah error while using it in JNI
它生成名为 example_com_myapplication_JniClass.h
的头文件,其中包含
#include <jni.h>
/* Header for class example_com_myapplication_JniClass */
#ifndef _Included_example_com_myapplication_JniClass
#define _Included_example_com_myapplication_JniClass
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: example_com_myapplication_JniClass
* Method: myFunction
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_example_com_myapplication_JniClass_myFunction
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
好的,现在你的答案。 简单的方法是复制生成的代码并将其粘贴到 File1.c 代码的底部。并实现它: 请注意,我在粘贴并清理注释后将参数命名为 env、obj 和 str
//..here your File1.c source code content
//
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_example_com_myapplication_JniClass_myFunction
(JNIEnv * env, jobject obj, jstring str){
const char * x=(*env)->GetStringUTFChars(env,str,0);
//call our function
int ret= myfunction(x);
(*env)->ReleaseStringUTFChars(env,str, x);
return ret;
}
#ifdef __cplusplus
}
#endif
但实际上您可能会在您的 C 代码中使用头文件。 例如,您可以添加生成的头文件并在 .c 文件中实现它。在 .c 文件中,您可以包含 File1.c header 。这样更干净。
假设您已经阅读了 ndk 教程。并且您设置了 ndk 工具并知道如何构建
最后我们将 File1.c 添加到 jni 文件夹并更改 Android.mk 文件
本地模块 := libraryWrapper LOCAL_SRC_FILES := 文件 1.c 和
APP_MODULES := libraryWrapper
然后我们使用 ndk-build 构建它,它将我们的 so 文件添加到 libs
Op 只需要 File1.c 和 File2.c 在 File2.c 中
//declaration of funtions inside File1.c
extern int myfunction(const char* st);
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_example_com_myapplication_JniClass_myFunction
(JNIEnv * env, jobject obj, jstring str){
const char * x=(*env)->GetStringUTFChars(env,str,0);
//call our function
int ret= myfunction(x);
(*env)->ReleaseStringUTFChars(env,str, x);
return ret;
}
#ifdef __cplusplus
}
#endif
并更改Android.mk
LOCAL_SRC_FILES := File1.c
LOCAL_SRC_FILES += File2.c
关于java - 从另一个库调用一个库函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32666116/