发布时间:2025-06-24 20:34:24  作者:北方职教升学中心  阅读量:978


创建Pointer:

//这样的指针变量定义很像C的写法,就是在定义的时候申请空间。

com.sun.jna.platform.unix.aix
Provides common library mappings for the AIX platform.

为AIX平台提供公共库映射。

struct_nested_param.c

#include<stdio.h>structUser{longid;char*name;intage;};structCompany{longid;constchar*name;structUserusers[3];intcount;};voidshowNestedStruct(structCompanycompany){printf("This is nested struct.\n");printf("company id is:%ld\n",company.id);printf("company name is:%s\n",company.name);for(inti =0;i <3;i++){printf("user[%d] info of companyn",i);printf("user id:%ldn",company.users[i].id);printf("user name:%sn",company.users[i].name);printf("user age:%dn",company.users[i].age);}printf("count %d\n",company.count);}

编译为共享库struct_nested_param.dylib:

gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin -dynamiclib-ostruct_nested_param.dylib struct_nested_param.c

JNA调用:

publicclassStructNestedParamTest{//描述本地共享库publicinterfaceLibStructNestedParamextendsLibrary{LibStructNestedParamINSTANCE=Native.load("/Users/acton_zhang/J2EE/MavenWorkSpace/java_safe_demo/src/main/java/pers/zhang/jna/struct_nested_param.dylib",LibStructNestedParam.class);//定义User结构体classUserStructextendsStructure{//公共字段的顺序,必须与C语言中的结构的顺序保持一致publicNativeLongid;publicStringname;publicintage;// 定义值传递和指针传递类publicstaticclassByReferenceextendsUserStructimplementsStructure.ByReference{//指针和引用的传递使用ByReference}publicstaticclassByValueextendsUserStructimplementsStructure.ByValue{//拷贝参数传递使用ByValue}// 重写getFieldOrder获取字段列表, 很重要,没有会报错@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"id","name","age"});}}//定义Company结构体classCompanyStructextendsStructure{//公共字段的顺序,必须与C语言中的结构的顺序保持一致publicNativeLongid;publicStringname;publicUserStruct.ByValue[]users =newUserStruct.ByValue[3];publicintcount;// 定义值传递和指针传递类publicstaticclassByReferenceextendsCompanyStructimplementsStructure.ByReference{//指针和引用的传递使用ByReference}publicstaticclassByValueextendsCompanyStructimplementsStructure.ByValue{//拷贝参数传递使用ByValue}// 重写getFieldOrder获取字段列表, 很重要,没有会报错@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"id","name","users","count"});}}//描述本地函数,值传递voidshowNestedStruct(CompanyStruct.ByValuecompany);}publicstaticvoidmain(String[]args){LibStructNestedParam.UserStruct.ByValueuser1 =newLibStructNestedParam.UserStruct.ByValue();user1.id =newNativeLong(1);user1.name ="zhangsan";user1.age =18;LibStructNestedParam.UserStruct.ByValueuser2 =newLibStructNestedParam.UserStruct.ByValue();user2.id =newNativeLong(2);user2.name ="lisi";user2.age =19;LibStructNestedParam.UserStruct.ByValueuser3 =newLibStructNestedParam.UserStruct.ByValue();user3.id =newNativeLong(3);user3.name ="wangwu";user3.age =20;LibStructNestedParam.CompanyStruct.ByValuecompany =newLibStructNestedParam.CompanyStruct.ByValue();company.id =newNativeLong(1000001);company.name ="XXXXXX有限责任公司";company.count =3;company.users[0]=user1;company.users[1]=user2;company.users[2]=user3;LibStructNestedParam.INSTANCE.showNestedStruct(company);}}

输出:

Thisis nested struct.company id is:1000001company name is:XXXXXX有限责任公司user[0]info of companyuser id:1user name:zhangsanuser age:18user[1]info of companyuser id:2user name:lisiuser age:19user[2]info of companyuser id:3user name:wangwuuser age:20count 3

4.5、

//设置intint_pointer.setInt(0,123);//设置doubledouble_pointer.setDouble(0,22.33);

Pointer的getXxx方法提供了为各种类型获取值的方法:
在这里插入图片描述

获取单个值的参数为偏移量,获取数组还需要传递一个获取数量。

com.sun.jna.platform.mac
Provides common library mappings for the OS X platform.

为OS X平台提供公共库映射。Structure类

  • 4.3、动态库和 jdk 的位数必须匹配
  • 5.5、

  • 2、概述

    JNA 全称 Java Native Access,是一个建立在经典的 JNI 技术之上的 Java 开源框架。案例

  • 3、正确的调用
  • 5、

  • com.sun.jna.platform.win32.COM.util
    Provides COM Utilities

    提供Com Utilities.

    com.sun.jna.platform.win32.COM.util.annotation
    Provides COM Utility annotations

    提供com实用程序注释

    com.sun.jna.platform.wince
    Provides common library mappings for the Windows CE platform.

    为Windows CE平台提供公共库映射。

    5.2、

    3.1、作为输入参数

    struct_nested_array_param.c

    #include<stdio.h>typedefstruct{intenable;intx;inty;intwidth;intheight;}area_pos;typedefstruct{intenable;intx;inty;}spot_pos;typedefstruct{intenable;intsta_x;intsta_y;intend_x;intend_y;}line_pos;typedefstruct{area_pos area[2];spot_pos spot[2];line_pos line;}image_pos;voidget_struct_array_value(image_pos *img_data){printf("line_pos enable:%d\n",img_data->line.enable);printf("line_pos sta_x:%d\n",img_data->line.sta_x);printf("line_pos sta_y:%d\n",img_data->line.sta_y);printf("line_pos end_x:%d\n",img_data->line.end_x);printf("line_pos end_y:%d\n",img_data->line.end_y);for(inti =0;i<2;i++){printf("area_pos[%d] enable:%dn",i,img_data->area[i].enable);printf("area_pos[%d] x:%dn",i,img_data->area[i].x);printf("area_pos[%d] y:%dn",i,img_data->area[i].y);printf("area_pos[%d] width:%dn",i,img_data->area[i].width);printf("area_pos[%d] height:%dn",i,img_data->area[i].height);}for(intj =0;j <2;j++){printf("spot_pos[%d] enable:%dn",j,img_data->spot[j].enable);printf("spot_pos[%d] x:%dn",j,img_data->spot[j].x);printf("spot_pos[%d] y:%dn",j,img_data->spot[j].y);}}

    编译为共享库struct_nested_array_param.dylib:

    gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin -dynamiclib-ostruct_nested_array_param.dylib struct_nested_array_param.c

    JNA调用:

    publicclassStructNestedArrayParamTest{publicinterfaceLibStructNestedArrayParamextendsLibrary{LibStructNestedArrayParamINSTANCE=Native.load("/Users/acton_zhang/J2EE/MavenWorkSpace/java_safe_demo/src/main/java/pers/zhang/jna/struct_nested_array_param.dylib",LibStructNestedArrayParam.class);classAreaPosextendsStructure{publicintenable;publicintx;publicinty;publicintwidth;publicintheight;publicstaticclassByReferenceextendsAreaPosimplementsStructure.ByReference{}publicstaticclassByValueextendsAreaPosimplementsStructure.ByValue{}@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"enable","x","y","width","height"});}}classSpotPosextendsStructure{publicintenable;publicintx;publicinty;publicstaticclassByReferenceextendsSpotPosimplementsStructure.ByReference{}publicstaticclassByValueextendsSpotPosimplementsStructure.ByValue{}@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"enable","x","y"});}}classLinePosextendsStructure{publicintenable;publicintsta_x;publicintsta_y;publicintend_x;publicintend_y;publicstaticclassByReferenceextendsLinePosimplementsStructure.ByReference{}publicstaticclassByValueextendsLinePosimplementsStructure.ByValue{}@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"enable","sta_x","sta_y","end_x","end_y"});}}classImagePosextendsStructure{publicAreaPos.ByValue[]area =newAreaPos.ByValue[2];publicSpotPos.ByValue[]spot =newSpotPos.ByValue[2];publicLinePos.ByValueline;publicstaticclassByReferenceextendsImagePosimplementsStructure.ByReference{}publicstaticclassByValueextendsImagePosimplementsStructure.ByValue{}@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"area","spot","line"});}}voidget_struct_array_value(ImagePos.ByReferenceimg);}publicstaticvoidmain(String[]args){LibStructNestedArrayParam.AreaPos.ByValuea1 =newLibStructNestedArrayParam.AreaPos.ByValue();a1.enable =1;a1.x =10;a1.y =20;a1.height =1080;a1.width =1920;LibStructNestedArrayParam.AreaPos.ByValuea2 =newLibStructNestedArrayParam.AreaPos.ByValue();a1.enable =0;a1.x =20;a1.y =10;a1.height =1920;a1.width =1080;LibStructNestedArrayParam.SpotPos.ByValues1 =newLibStructNestedArrayParam.SpotPos.ByValue();s1.enable =0;s1.x =1;s1.y =1;LibStructNestedArrayParam.SpotPos.ByValues2 =newLibStructNestedArrayParam.SpotPos.ByValue();s1.enable =1;s1.x =2;s1.y =2;LibStructNestedArrayParam.LinePos.ByValueline =newLibStructNestedArrayParam.LinePos.ByValue();line.enable =0;line.end_x =10;line.end_y =20;line.sta_x =30;line.sta_y =40;LibStructNestedArrayParam.ImagePos.ByReferenceimg =newLibStructNestedArrayParam.ImagePos.ByReference();img.area[0]=a1;img.area[1]=a2;img.spot[0]=s1;img.spot[1]=s2;img.line =line;LibStructNestedArrayParam.INSTANCE.get_struct_array_value(img);}}

    输出:

    line_pos enable:0line_pos sta_x:30line_pos sta_y:40line_pos end_x:10line_pos end_y:20area_pos[0]enable:0area_pos[0]x:20area_pos[0]y:10area_pos[0]width:1080area_pos[0]height:1920area_pos[1]enable:0area_pos[1]x:0area_pos[1]y:0area_pos[1]width:0area_pos[1]height:0spot_pos[0]enable:1spot_pos[0]x:2spot_pos[0]y:2spot_pos[1]enable:0spot_pos[1]x:0spot_pos[1]y:0
    2)、

    如果一个 Struct 有 2 个 int 变量 int a, int b,如果 JNA 中的次序和 C 语言中的次序相反,那么不会报错,但是数据将会被传递到错误的字段中去。

    5.4、

    这两个接口仅仅是标记:

    • 如果一个类实现 Structure.ByReference 接口,就表示这个类代表结构体指针。Java映射C数组乱码问题

    文件array_param.c

    #include<stdio.h>#include<string.h>typedefstruct{intenable;charstatic_ip[20];charnetmask[20];chargateway[20];chardns1[20];chardns2[20];}network_eth;intsdk_set_network_eth(constchar*ip,network_eth *network_param){if(strlen(ip)==0||network_param ==NULL){printf("sdk_set_network_eth param error!n");return-1;}printf("ip:%s\n",ip);printf("network_eth enable:%d\n",network_param->enable);printf("network_eth static_ip:%s\n",network_param->static_ip);printf("network_eth netmask:%s\n",network_param->netmask);printf("network_eth gateway:%s\n",network_param->gateway);printf("network_eth dns1:%s\n",network_param->dns1);printf("network_eth dns2:%s\n",network_param->dns2);return0;}

    编译为共享库array_param.dylib:

    gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin -dynamiclib-oarray_param.dylib array_param.c

    JNA调用:

    publicclassCharArrayTest{publicinterfaceLibCharArrayextendsLibrary{LibCharArrayINSTANCE=Native.load("/Users/acton_zhang/J2EE/MavenWorkSpace/java_safe_demo/src/main/java/pers/zhang/jna/array_param.dylib",LibCharArray.class);classNetWorkEthextendsStructure{publicintenable;publicbyte[]static_ip =newbyte[20];publicbyte[]netmask =newbyte[20];publicbyte[]gateway =newbyte[20];publicbyte[]dns1 =newbyte[20];publicbyte[]dns2 =newbyte[20];publicstaticclassByReferenceextendsNetWorkEthimplementsStructure.ByReference{}publicstaticclassByValueextendsNetWorkEthimplementsStructure.ByValue{}@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"enable","static_ip","netmask","gateway","dns1","dns2"});}}intsdk_set_network_eth(byte[]ip,NetWorkEth.ByReferencenetWork);}publicstaticvoidmain(String[]args){Stringip ="127.0.0.1";LibCharArray.NetWorkEth.ByReferencenetWorkEth =newLibCharArray.NetWorkEth.ByReference();netWorkEth.enable =1;netWorkEth.static_ip ="10.20.6.10".getBytes();netWorkEth.netmask ="255.255.255.0".getBytes();netWorkEth.gateway ="192.168.122.134".getBytes();netWorkEth.dns1 ="114.114.114.114".getBytes();netWorkEth.dns2 ="8.8.8.8".getBytes();intres =LibCharArray.INSTANCE.sdk_set_network_eth(ip.getBytes(),netWorkEth);System.out.println(res);}

    输出:

    0ip:127.0.0.1network_eth enable:1network_eth static_ip:10.20.6.10255.255.255.0192.168.122.134114.114.114.1148.8.8.8127.0.0.1network_eth netmask:5.0192.168.122.134114.114.114.1148.8.8.8127.0.0.1network_eth gateway:4.114.114.1148.8.8.8127.0.0.1network_eth dns1:127.0.0.1network_eth dns2:��#mRealVarArgsCheckerlang/O

    输出乱码!因为C/C++的数组类型在内存中是连续存储的,而Java的数组不一定是连续的。

    目标C程序,struct.c:

    #include<stdio.h>#include<stdlib.h>#include<string.h>// teacher 结构体定义typedefstruct{inttea_age;char*tea_name;}Teacher;// student 结构体定义typedefstruct{intstu_age;char*stu_name;}Student;Teacher stuTea(Student stu,Teacher *tea){printf("stu-name=%s/n",stu.stu_name);printf("stu-age=%d/n",stu.stu_age);// 将stu复制给tea做函数返回Teacher teacher;teacher.tea_name =stu.stu_name;teacher.tea_age =stu.stu_age;tea->tea_name =strcat(tea->tea_name,"是好老师");returnteacher;}

    函数内部的功能也简单:

    1. 打印stu的内容【验证值传递是否正确】
    2. 把stu的内容复制给结果变量teacher,用于函数返回【验证是否能返回结构体】
    3. 改变传入结构体变量tea的值【验证结构体引用传递是否生效】

    编译为共享库struct.dylib:

    gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin -dynamiclib-ostruct.dylib struct.c

    JNA调用:

    publicclassStructTest{//定义一个接口,描述本地库publicinterfaceLibStructextendsLibrary{LibStructINSTANCE=Native.load("/Users/acton_zhang/J2EE/MavenWorkSpace/java_safe_demo/src/main/java/pers/zhang/jna/struct.dylib",LibStruct.class);//定义结构体classTeacherStructextendsStructure{//结构体参数类型及顺序要严格按照C结构体的类型及顺序publicinttea_age;publicStringtea_name;// 定义值传递和指针传递类publicstaticclassByReferenceextendsTeacherStructimplementsStructure.ByReference{//指针和引用的传递使用ByReference}publicstaticclassByValueextendsTeacherStructimplementsStructure.ByValue{//拷贝参数传递使用ByValue}//重写getFieldOrder获取字段列表, 很重要,没有会报错@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"tea_age","tea_name"});}@OverridepublicStringtoString(){return"TeacherStruct{"+"tea_age="+tea_age +", tea_name='"+tea_name +'''+"} "+super.toString();}}//定义结构体classStudentStructextendsStructure{publicintstu_age;publicStringstu_name;// 定义值传递和指针传递类publicstaticclassByReferenceextendsStudentStructimplementsStructure.ByReference{//指针和引用的传递使用ByReference}publicstaticclassByValueextendsStudentStructimplementsStructure.ByValue{//拷贝参数传递使用ByValue}//重写getFieldOrder获取字段列表, 很重要,没有会报错@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"stu_age","stu_name"});}@OverridepublicStringtoString(){return"StudentStruct{"+"stu_age="+stu_age +", stu_name='"+stu_name +'''+"} "+super.toString();}}//描述本地函数TeacherStruct.ByValuestuTea(StudentStruct.ByValuestu,TeacherStruct.ByReferencetea);}publicstaticvoidmain(String[]args){LibStruct.StudentStruct.ByValuestuByValue =newLibStruct.StudentStruct.ByValue();LibStruct.TeacherStruct.ByReferenceteaByReference =newLibStruct.TeacherStruct.ByReference();stuByValue.stu_age =18;stuByValue.stu_name ="小学生";teaByReference.tea_age =48;teaByReference.tea_name ="高级教师";// 调用函数之前System.out.println("调用函数之前teaByReference:"+teaByReference.toString());// 调用方法。

    C函数文件test.c:

    inttest_pointer(inta,int*b){if(a <0){//未对*b进行处理return-1;}*b =a;return0;}

    编译为共享库test.dylib:

    gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin -dynamiclib-otest.dylib test.c

    使用JNA调用该共享库中的test_pointer函数:

    publicclassPointerTest{publicinterfaceLibPointerTestextendsLibrary{LibPointerTestINSTANCE=Native.load("/Users/acton_zhang/J2EE/MavenWorkSpace/java_safe_demo/src/main/java/pers/zhang/jna/test.dylib",LibPointerTest.class);inttest_pointer(inta,Pointerb);}publicstaticvoidmain(String[]args){inta =-10;Pointerb =newMemory(Native.getNativeSize(Integer.class));intadd =LibPointerTest.INSTANCE.test_pointer(a,b);System.out.println(add);System.out.println(a);System.out.println(b.getInt(0));}}

    输出:

    -1-100

    本文使用的为5.10版,并未发现垃圾值的问题。指针参数Pointer

    在JAVA中都是值传递,但是因为使用JNA框架,目标函数是C/C++是有地址变量的,很多时候都需要将变量的结果带回,因此,地址传递在JNA项目中几乎是必须的。

    当 C 函数的参数为 char*、动态库版本必须和系统类型匹配

    JNA

    1、使用场景

    结构体作为参数有两个点,一个是传入,一个是返回。甚至会因为我们对c和msg赋值导致C函数访问到奇怪的地址,导致报错。作为输出参数

    结构体中嵌套结构体数组用作输出参数时,需要对结构体数组的第一个元素赋初值。Java模拟C结构体

    • 4.1、返回结果LibStruct.TeacherStruct.ByValueresult =LibStruct.INSTANCE.stuTea(stuByValue,teaByReference);// 查看传地址的teaByReference的值是否变更System.out.println("调用函数之后teaByReference:"+teaByReference.toString());// 函数返回结果System.out.println("调用函数返回结果result.name:"+result.toString());}}

      输出:

      调用函数之前teaByReference:TeacherStruct{tea_age=48,tea_name='高级教师'}StructTest$LibStruct$TeacherStruct$ByReference(auto-allocated@0x7ffc36203c40(16bytes)){inttea_age@0x0=0x0030Stringtea_name@0x8=高级教师}调用函数之后teaByReference:TeacherStruct{tea_age=48,tea_name='高级教师是好老师'}StructTest$LibStruct$TeacherStruct$ByReference(auto-allocated@0x7ffc36203c40(16bytes)){inttea_age@0x0=0x0030Stringtea_name@0x8=高级教师是好老师}调用函数返回结果result.name:TeacherStruct{tea_age=18,tea_name='小学生'}StructTest$LibStruct$TeacherStruct$ByValue(auto-allocated@0x7ffc3620b480(16bytes)){inttea_age@0x0=0x0012Stringtea_name@0x8=小学生}stu-name=小学生/nstu-age=18/n

      4.2、如果使用的 jdk 和 dll 位数不同,会报 Unable to load DLL 'xxx.dll': 找不到指定的模块或者java.lang.UnsatisfiedLinkError: %1不是有效的 Win32 应用程序。开发人员只要在一个 java 接口中描述目标 native library 的函数与结构,JNA 将自动实现 Java 接口到native function 的映射。

      3.2、动态库和 jdk 的位数必须匹配

      64 位的 jdk 只能调用 64 位的 dll,32 位也一样。 各字段顺序对应结构体中的字段即可。错误的调用一

    • 2)、结构体数组做参数时, 要区别于非数组的 ByReference 和 ByValue。作为输入参数
    • 2)、

      4、

    使用这两个接口的实现类,可以明确定义我们的 Structure 实例表示的是结构体指针还是结构体本身。ByReference类

  • 3.3、结构体指针作为参数
  • 4.4、正确的调用
    publicclassStructArrayParamTest{publicinterfaceLibStructArrayParamextendsLibrary{LibStructArrayParamINSTANCE=Native.load("/Users/acton_zhang/J2EE/MavenWorkSpace/java_safe_demo/src/main/java/pers/zhang/jna/struct_array_param.dylib",LibStructArrayParam.class);classPersonextendsStructure{publicintage;publicbyte[]name =newbyte[20];@OverrideprotectedList<String>getFieldOrder(){returnArrays.asList(newString[]{"age","name"});}}//描述函数intchangeObjs(Person[]per,intsize);}publicstaticvoidmain(String[]args){LibStructArrayParam.Personper =newLibStructArrayParam.Person();LibStructArrayParam.Person[]pers =(LibStructArrayParam.Person[])per.toArray(2);pers[0].age =1;pers[0].name =Arrays.copyOf("tom".getBytes(),20);pers[1].age =2;pers[1].name =Arrays.copyOf("jerry".getBytes(),20);LibStructArrayParam.INSTANCE.changeObjs(pers,2);}}

    输出:

    person[0]age:10person[0]name:wokettasperson[1]age:20person[1]name:wokettas

    5、

    在这里插入图片描述

    创建ByReference:

    //无参构造,默认值为0IntByReferenceintRef =newIntByReference();//有参构造,根据指定值创建IntByReferenceintRef =newIntByReference(4);

    设置/获取值:

    //设置intRef.setValue(10);//获取intRef.getValue();

    3.3、常见问题

    5.1、示例二(调用自定义共享库)

  • 2、