Java使用JNA调用C文件

1.构建项目

准备最简单的maven项目,结构如下:
在这里插入图片描述
引入依赖:

<dependency>
      <groupId>net.java.dev.jna</groupId>
      <artifactId>jna</artifactId>
      <version>5.3.1</version>
    </dependency>

2.构建c文件和so文件

在resource目录下构建:

 #include <stdio.h>
 test() {
  printf("hello world\n");
}

编译生成so:

gcc test.c -fPIC -shared -o test.so

3.编写解析类和测试类

package org.linx;

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

public interface CLibrary extends Library {
    CLibrary INSTANCE = Native.loadLibrary("test.so", CLibrary.class);

    /**
     * 初始化SDK 注意:调用SDK其他接口前必须先调用此接口!
     */
    void test();

}

package org.linx;

import junit.framework.TestCase;
import org.junit.Test;

public class CLibraryTest extends TestCase {

    @Test
    public void testTest() {
        CLibrary.INSTANCE.test();
    }
}

tips:如果要把该项目打包为jar供其他项目使用,需要将so文件放置在特定目录下

在这里插入图片描述
访问不了的时候可以放在/usr/lib然后使用绝对路径

4.C与Java类型对应

C TypeJava Type
charbyte
wchar_tchar
shortshort
int 32-bit整型int
int boolean flagboolean
enumint (usually)
long longlong
floatfloat
doubledouble
void*Pointer
void**Pointer[]
char** 字符串数组String[]
wchar_t** 字符串数组(unicode)WString[]
struct* struct 结构体指针和结构体Structure
union 结构体Union
struct[] 结构体数组Structure[]
char*ByteByReference/Pointer
int*IntByReference
float*FloatByReference
double*DoubleByReference

结构体struct的写法:

@FieldOrder(value = {"x","y"})
public class Sm2PublicT extends Structure {
    public byte[] x;
    public byte[] y;

    Sm2PublicT(){
        x = new byte[64];
        y = new byte[64];
    }

    Sm2PublicT(byte[] x, byte[] y){
        this.x = x;
        this.y = y;
    }
    // 定义值传递和指针传递类
    public static class ByReference extends Sm2PublicT implements Structure.ByReference {
        //指针和引用的传递使用ByReference
    }
    public static class ByValue extends Sm2PublicT implements Structure.ByValue {
        //拷贝参数传递使用ByValue
    }
}

在返回值为结构体的时候,有时返回类型不能写Sm2PublicT而应该写Sm2PublicT.ByValue

关于ByReference和ByValue

  • 只要涉及到结构体的传递,必须使用ByReference或者ByValue中的一种
  • 指针和引用的传递使用ByReference
  • 拷贝参数传递使用ByValue

复杂的结构体传递可以参考:网址

本人实验char*可以使用Pointer:

Pointer id = new Memory(8);
id.setString(0, "myapp");

Pointer plain = new Memory(1024);

使用int*的时候:

IntByReference clen = new IntByReference(2048);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JNAJava Native Access)是一种 Java 编程语言的框架,它允许 Java 应用程序直接调用本地动态库(例如 .so 文件)中的函数。 下面是一个简单的示例程序,演示如何使用 JNA 调用本地动态库中的函数: 1. 首先,需要在 Java 代码中定义一个接口,用于描述要调用的本地函数。例如,如果要调用名为 `my_function` 的函数,可以定义如下接口: ```java import com.sun.jna.Library; import com.sun.jna.Native; public interface MyLibrary extends Library { MyLibrary INSTANCE = (MyLibrary) Native.loadLibrary("my_library", MyLibrary.class); void my_function(); } ``` 2. 然后,在 Java 代码中调用这个接口中定义的函数即可: ```java MyLibrary.INSTANCE.my_function(); ``` 3. 最后,需要将本地动态库文件(例如 my_library.so)放置到 Java 应用程序能够访问的路径中,例如运行程序时加上 `-Djava.library.path=/path/to/lib` 参数,或者将库文件放置到系统默认的库路径中。 需要注意的是,JNA调用本地函数时需要遵循特定的命名约定,例如在 Linux 系统下默认使用 C 语言的命名约定。如果本地函数使用了不同的命名约定,需要在 Java 代码中显式地指定。例如,如果本地函数使用了 C++ 语言的命名约定,可以在接口中添加 `@Name` 注解,例如: ```java public interface MyLibrary extends Library { MyLibrary INSTANCE = (MyLibrary) Native.loadLibrary("my_library", MyLibrary.class); @Name("my_function") void myFunction(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值