商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > JAVA JNA调用C接口的三种实现方式

JAVA JNA调用C接口的三种实现方式

  发布于2026-07-07 阅读(0)

扫一扫,手机访问

1. 准备一个共享库文件

先写一个简单的C函数,编译成动态库,后面所有调用都基于它。

#include 
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

nm -D查看符号表,确认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接口

新建一个普通Ma ven项目,引入JNA依赖:


    net.ja va.dev.jna
    jna
    5.5.0

定义接口继承Library,并加载动态库:

package jna;
import com.sun.jna.Library;
import com.sun.jna.Native;

public interface MyClibrary extends Library {
    MyClibrary INSTANTCE = Native.load("/root/libtest.so", MyClibrary.class);
    int test(String input);
}

测试代码:

import jna.MyClibrary;

public class Main {
    public static void main(String[] args) {
        int test = MyClibrary.INSTANTCE.test("extend Library");
        System.out.println(test);
    }
}

在Linux上运行Ja va程序,结果如下:

JA VA JNA调用C接口的三种实现方式

3. JNA方式2——直接NativeLibrary.getInstance

另一种方式不用定义接口,直接用NativeLibrary获取函数对象:

import com.sun.jna.Function;
import com.sun.jna.NativeLibrary;

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);
    }
}

4. JNA方式3——Native方法

如果希望用传统的JNI方式暴露本地方法,但又想保留JNA的灵活性,可以这样做。首先创建Ja va类声明native方法:

// 文件路径 /root/jna/MyNative.ja va
package jna;
import ja va.io.IOException;

public class MyNative {
     native int  test(String input) throws IOException;
}

编译并生成JNI头文件(注意JDK版本要一致,这里以JDK8为例):

 /usr/local/jdk1.8.0_111/bin/ja vac  MyNative.ja va
 /usr/local/jdk1.8.0_111/bin/ja vah -classpath /root/ -jni   jna.MyNative

然后实现头文件中的接口。可以直接在Linux上编辑C源文件:

#include 
#include 
#include "jna_MyNative.h"
jint  Ja va_jna_MyNative_test(JNIEnv *jniEnv, jobject clazz, jstring input){
    printf("input:%s\n",(char *)input);
    return 0;
}

编译时注意引入JDK头文件路径:

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项目,引入头文件并实现方法:

JA VA JNA调用C接口的三种实现方式

几点注意事项:

  • 如果使用远程toolchain和CMake,注意CMake版本可能导致include_directories(SYSTEM "/usr/lib/jvm/jdk-17-oracle-x64/include")同步失败,本地找不到符号,但实际可以正常运行。
  • jniEnv指针必须由Ja va调用时才会被正确赋值。

CMake配置示例:

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)

Ja va侧调用测试:

import jna.MyNative;
import ja va.io.IOException;

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是以JNI风格实现的,但生成的libtest.so依然可以被前两种JNA方式调用,只是函数名变成了Ja va_jna_MyNative_test

[root@node-126 lib]# nm -D /usr/lib/libtest.so 
0000000000201070 B __bss_start
...
0000000000000a15 T Ja va_jna_MyNative_test
...

总结

以上是JNA调用C接口的三种常见做法:继承Library接口、直接操作NativeLibrary、以及结合JNI声明native方法。每种方式各有适用场景,开发者可以根据实际项目需求灵活选择。

本文转载于:https://www.jb51.net/program/363335dzr.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注