因业务需要,需使用Java调用C++ so动态库,研究了几天,调试通了,发现现有资料比较零散,本文做个汇总。
一。C++生成so动态库
//cplus.cpp
#include<stdio.h>
#include<iostream>
int addCplus(int x, int y) {
printf("add by C++\n");
std::cout << "generate a c++ library" << std::endl;
return x + y;
}
编译
g++ -m64 -fPIC --shared -o libcplus.so cplus.cpp
移动编译好的so动态库到/usr/lib 用户库目录下,便于其他程序调用
sudo cp libcplus.so /usr/lib/
关于linux下libxxx.so动态库位置
建议放到/usr/lib目录下,执行命令ldconfig重新加载动态库即可。
sudo ldconfig
二。 中间接口库生成so动态库
//mid.cpp
#include "iostream"
int addCplus(int a, int b);
#ifdef __cplusplus
extern "C" {
#endif
int m_addCplus(int x, int y)
{
return addCplus(x, y);
}
#ifdef __cplusplus
}
#endif
编译,其中-l cplus 来自于libcplus.so动态库文件名
g++ -m64 -fPIC --shared -o libmid.so mid.cpp -l cplus
移动编译好的so动态库到/usr/lib用户库目录下,便于其他程序调用
sudo cp libmid.so /usr/lib/
三。C 调用C++
//test.c
#include <stdio.h>
int main()
{
int res=m_addCplus(3,5);
printf("res=%d\n",res);
return 0;
}
编译,其中-l mid 来自于libmid.so动态库文件名
gcc test.c -l mid -o test
运行
» ./test
add by C++
generate a c++ libraryres=8
gcc test.c -lmid -o test -L./
//大L指定路径,小l指定库名,这种使用方法,有时会显示找不到库,需要配置库路径环境变量
//export LD_LIBRARY_PATH="data/chenxiaohui/SIFT3D-1.4.6-Linux/usr/local/lib/sift3d:$LD_LIBRARY_PATH"
或者gcc test.c -o test /usr/lib/libmid.so
//直接路径+名字
注意事项:如果在板子上运行的话,可以用export LD_LIBRARY_PATH声明库的路径比如mount,nfs在/mnt,把库放到/mnt里面然后export LD_LIBRARY_PATH="/mnt:$LD_LIBRARY_PATH"就可以让程序找到了
四。Java调用C++
pom.xml引入maven
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>platform</artifactId>
<version>3.5.2</version>
</dependency>
1.类直接调用so动态库
package com.xx.xx;
import com.sun.jna.Native;
/**
* Demo1.java
*
* @author :qiyu
* @version :1.0
* @description: 类中直接调用so动态库
* @date :2023/6/26 上午9:09
*/
public class Demo1 {
static {
Native.register("libmid.so");
}
public static native int m_addCplus(int x, int y);
public static void main(String[] args) {
System.out.println("java.library.path:" + System.getProperty("java.library.path"));
System.out.println("***************************");
System.out.println(m_addCplus(1, 2));
System.out.println("***************************");
}
}
运行结果
java.library.path:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
***************************
add by C++
generate a c++ library
3
***************************
2.接口实现,便于复用
接口
package com.xx.xx;
import com.sun.jna.Library;
import com.sun.jna.Native;
/**
* MySo.java
* @author :qiyu
* @version :1.0
* @description: 接口调用so动态库,便于其他类调用
* @date :2023/6/26 上午10:34
*/
public interface MySo extends Library {
MySo myso = (MySo) Native.load("libmid.so", MySo.class);
int m_addCplus(int x, int y);
}
类调用接口
package com.xx.xx;
import java.io.IOException;
/**
* Main.java
*
* @author :qiyu
* @version :1.0
* @description:调用接口
* @date :2023/6/26 上午10:35
*/
public class Main {
public static void main(String[] args) throws IOException {
System.out.println("java.library.path:" + System.getProperty("java.library.path"));
// System.out.println("是Linux平台?=" + Platform.isLinux());
int value = MySo.myso.m_addCplus(1, 1);
System.out.println("value=" + value);
}
}
运行类Main方法
java.library.path:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
add by C++
generate a c++ library
value=2
五。Java/C/C++数据类型映射
JNA实战系列:JNA与C语言中的数据类型映射以及复杂结构体传参示例_jna 类型映射_wangzhongyudie的博客-CSDN博客
参考:
C代码调用C++编译的so库_c调用c++ so_I&You的博客-CSDN博客