文章目录
- 1. 准备一个共享库文件
- 2. JNA姿势1—继承Library接口
- 3. JNA姿势2—直接NativeLibrary.getInstance
- 3. JNA姿势3—Native方法
1. 准备一个共享库文件
test.c
#include <stdio.h>
int test(char *input){
printf("input:%s\n",input);
return 0;
}
libtest.so
[root@node-126 ~]# gcc -fPIC -shared -o libtest.so test.c
[root@node-126 ~]# ls /root/
anaconda-ks.cfg libtest.so node-v6.10.2-linux-x64.tar.xz original-ks.cfg spring3 test test.c
可以看到有test方法
[root@node-126 ~]# nm -D libtest.so
0000000000201038 B __bss_start
w __cxa_finalize
0000000000201038 D _edata
0000000000201040 B _end
0000000000000600 T _fini
w __gmon_start__
00000000000004c0 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U printf
00000000000005d5 T test
2. JNA姿势1—继承Library接口
建个普通maven项目
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.5.0</version>
</dependency>
package jna;
import com.sun.jna.Library;
import com.sun.jna.Native;
/**
* 接口继承
*
* @author majun
* @version 1.0
* @since 2023-08-22 22:27
*/
public interface MyClibrary extends Library {
MyClibrary INSTANTCE = Native.load("/root/libtest.so", MyClibrary.class);
int test(String input);
}
测试
import jna.MyClibrary;
/**
* TODO
*
* @author majun
* @version 1.0
* @since 2023-03-31 7:44
*/
public class Main {
public static void main(String[] args) {
int test = MyClibrary.INSTANTCE.test("extend Library");
System.out.println(test);
}
}
使用Linux上的Java运行
3. JNA姿势2—直接NativeLibrary.getInstance
import com.sun.jna.Function;
import com.sun.jna.NativeLibrary;
/**
* TODO
*
* @author majun
* @version 1.0
* @since 2023-03-31 7:44
*/
public class Main {
public static void main(String[] args) {
NativeLibrary instance = NativeLibrary.getInstance("/root/libtest.so");
Function func = instance.getFunction("test");
Object res = func.invoke(Integer.class, new Object[]{"NativeLibrary.getInstance"});
System.out.println( res);
}
}
3. JNA姿势3—Native方法
mkdir -p /root/jna && cd /root/jna
新建MyNative.java
package jna;
import java.io.IOException;
public class MyNative {
native int test(String input) throws IOException;
}
编译并生成头文件(这里java17没找到javah命令,改用java8的,但注意javac ,javah要使用同一个Java版本的)
/usr/local/jdk1.8.0_111/bin/javac MyNative.java
/usr/local/jdk1.8.0_111/bin/javah -classpath /root/ -jni jna.MyNative
linux直接编辑实现头文件中的接口:
#include <stdio.h>
#include <jni.h>
#include "jna_MyNative.h"
jint Java_jna_MyNative_test(JNIEnv *jniEnv, jobject clazz, jstring input){
printf("input:%s\n",(char *)input);
return 0;
}
编译时注意引入jdk头文件包下的jni.h等
gcc -fPIC -shared -I/usr/lib/jvm/jdk-17-oracle-x64/include -I/usr/lib/jvm/jdk-17-oracle-x64/include/linux -o libtest.so test.c
使用Clion实现头文件的接口:新建C项目,引入jna_MyNative.h,并实现其中的方法
注意
1.使用远程toolchain,cmake编译安装运行,注意cmake版本可能导致include_directories(SYSTEM "/usr/lib/jvm/jdk-17-oracle-x64/include")
同步Linux上jdk的头文件失败,本地无法找到符号,但可以正常运行。
2.jniEnv必须Java调用才会有值。
cmake_minimum_required(VERSION 2.8)
project(untitled1)
set(CMAKE_CXX_STANDARD 17)
include_directories(SYSTEM "/usr/lib/jvm/jdk-17-oracle-x64/include")
include_directories(SYSTEM "/usr/lib/jvm/jdk-17-oracle-x64/include/linux")
add_executable(testexe main.cpp)
add_library(test SHARED main.cpp jna_MyNative.h)
target_link_libraries(test -I/usr/lib/jvm/jdk-17-oracle-x64/include -I/usr/lib/jvm/jdk-17-oracle-x64/linux)
install(TARGETS test LIBRARY DESTINATION /usr/lib)
Java调用测试
import jna.MyNative;
import java.io.IOException;
/**
* TODO
*
* @author majun
* @version 1.0
* @since 2023-08-23 23:44
*/
public class Main {
public static void main(String[] args) throws IOException {
System.load("/root/jna/libtest.so");
//System.loadLibrary("test");// 自动拼接成libtest.so,默认从/usr/lib,/usr/lib64等路径找
MyNative myNative = new MyNative();
int test = myNative.test("native");
System.out.println(test);
}
}
姿势3实现的C接口,Java依旧可以使用姿势1,2的方式来调用,注意函数名为Java_jna_MyNative_test
[root@node-126 lib]# nm -D /usr/lib/libtest.so
0000000000201070 B __bss_start
U __cxa_allocate_exception
w __cxa_finalize
U __cxa_free_exception
U __cxa_throw
0000000000201070 D _edata
0000000000201078 B _end
0000000000000b4c T _fini
w __gmon_start__
U __gxx_personality_v0
0000000000000860 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000000a15 T Java_jna_MyNative_test
w _Jv_RegisterClasses
0000000000000ac8 T main
U printf
U _Unwind_Resume
0000000000000b18 W _ZN7JNIEnv_8ThrowNewEP7_jclassPKc
0000000000000aea W _ZN7JNIEnv_9FindClassEPKc
U _ZTIi