java - 从另一个库调用一个库函数

标签 java android c++ c

我有一个库 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.JniClass

如果您遇到错误,请参阅 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/

相关文章:

java - 从 Activity 的 fragment 中获取一个按钮

c++ - 优化此功能(在 C++ 中)

C++ 函数 : invalid initialization of non-const reference of type

c++ - 如何正确更新几何图形

java - Firebase 数据库查询返回错误结果

java - Jersey 服务和持久层

android - 单击 GridView android时打开全屏图像

java - 在 ComboBox 中显示两个或多个属性?

java - 如何使用 Gradle 7.0 发布到 Maven Repo

Android:比 android:ellipsize ="end"添加 "..."到截断的长字符串更好的东西?