JNA中使用不同的接口来映射C中的结构体,指针,函数指针等概念。所以下面列举一个很经典的例子。
调用DLL
1. 在VS中创建一个DLL项目。
选择创建Win32 Console Application,然后选择DLL
2. 编写Demo
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
using namespace std;
#define MYLIB extern "C" __declspec(dllexport)
extern "C"{
MYLIB typedef void(*OpenFun)(const char*, int);
OpenFun openfun=NULL;
MYLIB void init(OpenFun fun){
cout << "init fun" << endl;
openfun = *fun;
}
MYLIB void test(){
if (openfun == NULL)
cout << "openfun is null" << endl;
(*openfun)("test", 1);
}
}
解释: 以上代码声明一个函数指针类型 OpenFun ,然后定义两个函数init和test 其中init函数中初始化openfun ,然后在test中调用openfun函数。其中MYLIB 是一个宏,为了将函数指针和函数进行导出。
3. 编译DLL, 编译为x64
4. 编写JAVA代码,并导入DLL文件(DLL文件放在工程bin目录下)
//Clib.java
package com.java;
import com.sun.jna.Callback;
import com.sun.jna.Library;
public interface Clib extends Library{
public interface OpenFun extends Callback{
void callIn(String filename,int i);
}
void init(OpenFun openfun);
void test();
}
//HelloTest.java
package com.java;
import com.sun.jna.Native;
public class HelloTest {
public static void main(String[] args) {
Clib lib=(Clib) Native.loadLibrary("Mylib", Clib.class);
lib.init(new Clib.OpenFun() {
public void callIn(String filename, int i) {
// TODO Auto-generated method stub
System.out.println("callback called");
System.out.println(filename);
}
});
lib.test();
}
}
解释: Clib.java 主要就是完成和C代码的一个映射,用继承callback 接口映射 函数指针,其中继承callback接口的名称要跟C代码中函数指针类型一致,然后接口中定义一个函数,用来实现函数内容,其中函数参数需要跟C代码中函数参数一致。函数名称可以自定义。
HelloTest 中主要完成加载动态库,其中Native.loadLibrary会在指定的位置加载Mylib.dll或libMylib.so ,根据Java程序跑在windows还是linux上。然后调用到C代码中init函数来初始化函数指针,其中这个函数指针对应的函数在java中实现。然后调用test。
运行结果:
调用so文件
生成动态库
//Mylib.c
#include <stdlib.h>
#include <stdio.h>
typedef void(*OpenFun)(const char*, int);
OpenFun openfun=NULL;
void init(OpenFun fun)
{
openfun = *fun;
}
void test()
{
if (openfun == NULL)
printf("openfun is null");
(*openfun)("test", 1);
}
在linux上通过 gcc Mylib.c -fPIC -shared -o libMylib.so
java代码依然使用上述的代码,不过在linux上使用java命令行来编译。 需要将Clib.java 和HelloTest.java中package com.java 删除掉。
如何在linux上安装jdk以及配置环境变量参考以下文章: https://www.cnblogs.com/panzhaohui/p/6306675.html
然后将jna对象的jar拷贝到linux机器上。我们目录如下图所示,将libMylib.so jna-4.0.0.jar 以及java源码放在同一个目录,当然也可以将libMylib.so 动态库按照linux上查找动态库的路径 放置在某一处可以被查找即可。
1. 编译java
javac -classpath jna-4.0.0.jar Clib.java HelloTest.java
2. 执行java程序
java -classpath .:jna-4.0.0.jar HelloTest
这里我们可以看到成功调用了so动态库。
参考的文章:https://www.cnblogs.com/zhanglinfan/articles/5078548.html
https://www.cnblogs.com/chaofn/p/9939761.html
linux上动态库查找的路径和修改:https://blog.csdn.net/f110300641/article/details/82657972