Java使用JNA调用C文件

本文介绍了如何构建一个简单的Maven项目,引入JNA库来调用C语言编写的动态库。首先创建包含C代码的资源文件并编译为SO文件,然后在Java中定义接口并加载SO文件进行调用。此外,文章还讨论了C与Java类型对应关系,以及结构体在JNA中的处理方式,包括ByReference和ByValue的使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值