Java调用动态链接库so文件

本文详细介绍了如何在Java中调用Linux下的动态链接库(SO文件),包括生成SO文件的两种方法,以及解决调用过程中遇到的找不到方法、返回值乱码等问题。通过Java的jna包实现参数传递,并展示了获取字符串返回值的正确方式。
摘要由CSDN通过智能技术生成

Java调用动态链接库so文件(传参以及处理返回值问题)

刚来到公司,屁股还没坐稳,老板把我叫到办公室,就让我做一个小程序。我瞬间懵逼了。对小程序一窍不通,还好通过学习小程序视频,两天的时间就做了一个云开发的小程序,但是领导不想核心的代码被别人看到,给了我一个dll文件。找了大量的资料,还是用Java做吧,于是又快速的用Java搭建了一个后台,测试了一下,发现dll调用成功了,但是在发布到服务器上的时候,dll文件又不行了,又找方法。发现so文件和dll文件一样,都是打包生成的动态链接库,于是就在服务器上测试调用so文件,在调用so文件的时候出现了很多的问题,例如so文件生成失败、调用so文件找不到里面的方法、返回值出现乱码等。

一、生成so文件(Limux下操作)

1.把.h文件和.cpp文件放到一起(随意了想咋放都行 执行命令的时候地址写对就好)

test.h文件只写.cpp文件里面的方法名

1
void Test01();
   test.cpp文件

1
2
3
4
5
6
7
#include <stdio.h>
#include “test.h”

void Test01()
{
printf(“TestA func\n”);
}

生成so文件的命令(在文件的路径下执行)

1
g++ test.cpp -fPIC -shared -o libtest.so
  so文件以lib开头(lib**.so)

这种方式生成的so文件有时在Java后端调用的时候报找不到指定方法的错误。然后找了好久找到一个方法给我解决了这个问题(看第二种生成so文件的方式)。(如果这个方法你们不适用,那就另找解决方式吧)

2.不要.h文件了直接用.cpp文件

复制代码
1 #include <stdio.h>
2 #include “test.h”
3
4 extern “C” void Test01()
5 {
6 printf(“TestA func\n”);
7 }
复制代码
方法的前面以 extern “C” 开头,用这种方式对方法进行声明。

2.通过Java的jna包调用so文件进行传参(直接上代码)

复制代码
public interface CLibrary extends Library {

        // DLL文件默认路径为项目根目录,若DLL文件存放在项目外,请使用绝对路径。(此处:(Platform.isWindows()?"msvcrt":"c")指本地动态库msvcrt.dll)
                CLibrary INSTANCE = (CLibrary) Native.loadLibrary(("/usr/lib/libtest.so"),
                CLibrary.class);
                
        // 声明将要调用的so中的方法,可以是多个方法(此处示例调用so动态库libtest.so中的Test01()方法)
                void Test01(String str, int num);
                
       
    }

复制代码
1 public static void main(String[] args) {
2 String cou = CLibrary.INSTANCE.Test01(“hi”,123);
3 System.out.println(cou);
4
5 }
3.又是调用so文件返回值是字符串的时候会出现乱码(解决方法如下)

通过用Pointer来获取返回值,而so链接库的返回值要存到指针里面

Java代码:

复制代码
public interface CLibrary extends Library {

        // DLL文件默认路径为项目根目录,若DLL文件存放在项目外,请使用绝对路径。(此处:(Platform.isWindows()?"msvcrt":"c")指本地动态库msvcrt.dll)
                CLibrary INSTANCE = (CLibrary) Native.loadLibrary(("/usr/lib/libtest.so"),
                CLibrary.class);
                
        // 声明将要调用的so中的方法,可以是多个方法(此处示例调用so动态库libtest.so中的Test01()方法)
                void Test01(String str, int num,Pointer p);
                
       
    }

复制代码
复制代码
public static void main(String[] args) {

     Pointer p = new Memory(22);
     CLibrary.INSTANCE.Test01("hi", 123, p);
     
     for(int i=0, sumi=21; i< sumi; i++){
         
         System.out.print((char) p.getByteArray(0, 21)[i]);
         
                 }
}

复制代码
so链接库方法声明方式:

复制代码
extern “C” void Test01(char* str, unsigned int num, char* strReturn){


     *****************
       **********

return *****;
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java可以通过Java Native Interface(JNI)调用C或C++编写的动态链接库(也就是Windows下的.dll文件,Linux下的.so文件)。以下是一些简单的步骤: 1. 编写C或C++代码并将其编译为动态链接库文件(.dll或.so文件)。 2. 在Java中使用JNI接口声明与C或C++代码中的函数对应的Java本地方法,并将其实现为Java本地方法。 3. 编译Java代码并将其打包成jar文件。 4. 将生成的动态链接库文件放到Java程序能够访问到的目录下。 5. 运行Java程序。 以下是一个简单的示例: 1. 编写C代码 ```c #include <stdio.h> #include "jni.h" JNIEXPORT void JNICALL Java_com_example_Test_print(JNIEnv *env, jobject obj, jstring str) { const char *c_str = (*env)->GetStringUTFChars(env, str, NULL); printf("%s\n", c_str); (*env)->ReleaseStringUTFChars(env, str, c_str); } ``` 函数名必须以Java_开头,并加上Java类的完整路径和方法名。 2. 编译动态链接库文件 假设我们已经将上述代码保存为test.c文件,可以使用以下命令将其编译为动态链接库文件: - Windows:gcc -shared -o test.dll test.c -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" - Linux:gcc -shared -o libtest.so test.c -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" 注意:这里需要将JDK的include目录和平台相关的include目录添加到编译选项中。 3. 在Java中声明本地方法 ```java public class Test { static { System.loadLibrary("test"); // 加载动态链接库文件 } public static native void print(String str); } ``` 4. 实现Java本地方法 ```java Test.print("Hello, world!"); // 调用本地方法 ``` 这样就可以在Java调用C代码了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值