JNA实践之Java模拟C结构体、结构体指针、结构体数组

news2024/11/14 1:51:23

目录

  • 1 JNA模拟C结构体
    • 1.1 结构体本身作参数
    • 1.2 结构体指针作参数
    • 1.3 结构体内部嵌套结构体(结构体本身作参数)
    • 1.4 结构体指针作参数
  • 2 结构体中嵌套结构体数组
    • 2.1 用作输入
    • 2.2 用作输出
  • 3 结构体数组作参数
    • 典型错误1--内存不连续
    • 典型错误2--误用ByValue
  • 4 Java映射C中char[]类型
  • 5 常见问题及其解决方法

第一次写JNA相关的文章是在21年了,中间由于一些事情把后续搁置了,现在补上Java模拟结构体、结构体指针以及结构体中嵌套结构体数组。如果对JNA还不了解,可以先阅读 JNA模拟复杂的C类型一文。

1 JNA模拟C结构体

        要使用Java类模拟C的结构体,需要Java类继承Structure 类。必须注意,Structure 子类中的公共字段的顺序,必须与C语言中的结构的顺序保持一致,否则会报错!因为,Java 调用动态链接库中的C 函数,实际上就是一段内存作为函数的参数传递给C函数。动态链接库以为这个参数就是C 语言传过来的参数。同时,C 语言的结构体是一个严格的规范,它定义了内存的次序。因此,JNA 中模拟的结构体的变量顺序绝对不能错。
        如果一个Struct 有2个int 变量int a, int b,如果JNA 中的顺序和C 语言中的顺序相反,那么不会报错,但是数据将会被传递到错误的字段中去。
        Structure 类代表了一个原生结构体。当Structure 对象作为一个函数的参数或者返回值传递时,它代表结构体指针。当它被用在另一个结构体内部作为一个字段时,它代表结构体本身。
        另外,Structure 类有两个内部接口Structure.ByReference 和Structure.ByValue。这两个接口仅仅是标记,如果一个类实现Structure.ByReference 接口,就表示这个类代表结构体指针。如果一个类实现Structure.ByValue 接口,就表示这个类代表结构体本身。如果不实现这两个接口,那么就相当于你实现了Structure.ByReference 接口。使用这两个接口的实现类,可以明确定义我们的Structure 实例表示的是结构体指针还是结构体本身。

1.1 结构体本身作参数

假设有这样一个C语言结构体:

struct User{
    long id;
    char* name;
    int age;
};

使用上述结构体的函数:

extern "C"{
void sayUser(User user);
}
void sayUser(User user){
    printf("id:%ld\n",user.id);
    printf("name:%s\n",user.name);
    printf("age:%d\n",user.age);
}

JNA中可以这样写:

public class Test {
    public interface CLibrary extends Library {

        CLibrary INSTANCE = (CLibrary) Native.loadLibrary("/libJNADEMO.so", CLibrary.class);
		
		public static class UserStruct extends Structure{
            public NativeLong id;
            public String name;
            public int age;
            public static class ByReference extends UserStruct implements Structure.ByReference{}
            public static class ByValue extends  UserStruct implements Structure.ByValue{}

            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"id", "name", "age"});
            }
        }
        void sayUser(UserStruct.ByValue user);
	}
	
	public static void main(String[] args) {
		CLibrary.UserStruct.ByValue user = new CLibrary.UserStruct.ByValue();
		user.id = new NativeLong(100001);
		user.name = "张三";
		user.age = 29;
		CLibrary.INSTANCE.sayUser(user);
	}
}

运行结果如下:
在这里插入图片描述

1.2 结构体指针作参数

仍然使用1.1中的结构体,C函数修改为下面的:

extern "C"{
	void sayUser(User* user);
}
void sayUser(User *user){
    printf("use structure pointer\n");
    printf("id:%ld\n",user->id);
    printf("name:%s\n",user->name);
    printf("age:%d\n",user->age);
}

JNA代码中,修改函数声明为:
void sayUser(UserStruct.ByReference user);
JNA main函数中修改为:

CLibrary.UserStruct.ByReference user = new CLibrary.UserStruct.ByReference();
user.id = new NativeLong(100390301);;
user.name = "test";
user.age = 29;
CLibrary.INSTANCE.sayUser(user);

运行结果如下:
在这里插入图片描述

1.3 结构体内部嵌套结构体(结构体本身作参数)

C语言最复杂的数据类型就是结构体。结构体的内部可以嵌套结构体,这使它可以模拟任何类型的对象。JNA 也可以模拟这类复杂的结构体,结构体内部可以包含结构体对象指针的数组。
假设有如下结构体:

struct User{
    long id;
    char* name;
    int age;
};

struct CompanyStruct{
    long id;
    const char* name;
    User users[3];
    int count;
};

如下的C函数:

// 头文件函数声明
extern "C"{
	void showNestedStruct(CompanyStruct cst); //结构体本身做参数
}
// 函数定义
void showNestedStruct(CompanyStruct cst){
    printf("This is nested struct\n");
    printf("company id is:%ld\n",cst.id);
    printf("company name:%s\n",cst.name);
    for (int i = 0; i < 3; i++){
        printf("user[%d] info of company\n",i);
        printf("user id:%ld\n",cst.users[i].id);
        printf("user name:%s\n",cst.users[i].name);
        printf("user age:%d\n",cst.users[i].age);
    }
    printf("count %d\n",cst.count);
}

JNA代码:

import com.sun.jna.*;
import java.util.Arrays;
import java.util.List;

public class Test {
    public interface CLibrary extends Library {

        CLibrary INSTANCE = (CLibrary) Native.loadLibrary("/libJNADEMO.so", CLibrary.class);


        public static class UserStruct extends Structure{
            public NativeLong id;
            public String name;
            public int age;
            public static class ByReference extends UserStruct implements Structure.ByReference{}
            public static class ByValue extends  UserStruct implements Structure.ByValue{}

            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"id","name","age"});
            }
        }

        public static class CompanyStruct extends Structure{
            public NativeLong id;
            public String name;
            public UserStruct.ByValue[] users = new CLibrary.UserStruct.ByValue[3];
            public int count;
            public static class ByReference extends CompanyStruct implements Structure.ByReference{};
            public static class ByValue extends CompanyStruct implements Structure.ByValue{};

            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"id","name","users","count"});
            }
        }



        //函数声明, 对应C函数void showNestedStruct(CompanyStruct cst);
        void showNestedStruct(CompanyStruct.ByValue com); 

    } // interface

    public static void main(String[] args) {
        CLibrary.UserStruct.ByValue user1 = new CLibrary.UserStruct.ByValue();
        user1.id = new NativeLong(100001);
        user1.name = "张三";
        user1.age = 19;

        CLibrary.UserStruct.ByValue user2 = new CLibrary.UserStruct.ByValue();
        user2.id = new NativeLong(100002);
        user2.name = "关羽";
        user2.age = 23;

        CLibrary.UserStruct.ByValue user3 = new CLibrary.UserStruct.ByValue();
        user3.id = new NativeLong(100003);
        user3.name = "test";
        user3.age = 25;

        CLibrary.CompanyStruct.ByValue cst = new CLibrary.CompanyStruct.ByValue();
        cst.id = new NativeLong(30001);
        cst.name = "technology";
        cst.count = 3;
        cst.users[0] = user1;
        cst.users[1] = user2;
        cst.users[2] = user3;
        CLibrary.INSTANCE.showNestedStruct(cst); //调用动态库中的函数
    }
}

运行结果:
在这里插入图片描述

1.4 结构体指针作参数

使用1.3中的结构体,假设有如下C函数:

extern "C"{
	void showNestedStructWithPointer(CompanyStruct* cst);
}

函数定义如下

void showNestedStructWithPointer(CompanyStruct *cst){
	printf("This is nested struct pointer\n");
	printf("company id is:%ld\n",cst->id);
	printf("company name:%s\n",cst->name);
	for (int i = 0; i < 3; i++){
		printf("user[%d] info of company\n",i);
		printf("user id:%ld\n",cst->users[i].id);
		printf("user name:%s\n",cst->users[i].name);
		printf("user age:%d\n",cst->users[i].age);
	}
	printf("count %d\n",cst->count);
}

JNA代码:

import com.sun.jna.*;
import java.util.Arrays;
import java.util.List;

public class Test {
    public interface CLibrary extends Library {

        CLibrary INSTANCE = (CLibrary) Native.loadLibrary("/libJNADEMO.so", CLibrary.class);


        public static class UserStruct extends Structure{
            public NativeLong id;
            public String name;
            public int age;
            public static class ByReference extends UserStruct implements Structure.ByReference{}
            public static class ByValue extends  UserStruct implements Structure.ByValue{}

            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"id","name","age"});
            }
        }

        public static class CompanyStruct extends Structure{
            public NativeLong id;
            public String name;
            public UserStruct.ByValue[] users = new CLibrary.UserStruct.ByValue[3];
            public int count;
            public static class ByReference extends CompanyStruct implements Structure.ByReference{};
            public static class ByValue extends CompanyStruct implements Structure.ByValue{};

            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"id","name","users","count"});
            }
        }



        //函数声明
        void showNestedStructWithPointer(CompanyStruct.ByReference cbr);

    } // interface

    public static void main(String[] args) {
	    System.out.println("showNestedStructWithPointer");
        CLibrary.UserStruct.ByValue user1 = new CLibrary.UserStruct.ByValue();
        user1.id = new NativeLong(100001);
        user1.name = "张三";
        user1.age = 19;

        CLibrary.UserStruct.ByValue user2 = new CLibrary.UserStruct.ByValue();
        user2.id = new NativeLong(100002);
        user2.name = "李四";
        user2.age = 23;

        CLibrary.UserStruct.ByValue user3 = new CLibrary.UserStruct.ByValue();
        user3.id = new NativeLong(100003);
        user3.name = "test";
        user3.age = 25;

        CLibrary.CompanyStruct.ByReference cbr = new CLibrary.CompanyStruct.ByReference();
        cbr.id = new NativeLong(30001);
        cbr.name = "TEST";
        cbr.users[0] = user1;
        cbr.users[1] = user2;
        cbr.users[2] = user3;
        cbr.count = 3;
        CLibrary.INSTANCE.showNestedStructWithPointer(cbr);
    }
}

运行结果
在这里插入图片描述

2 结构体中嵌套结构体数组

2.1 用作输入

假设有下面的结构体:

typedef struct
{
    int enable;
    int x;
    int y;
    int width;
    int height;
} area_pos;

typedef struct
{
    int enable;
    int x;
    int y;
} spot_pos;

typedef struct
{
    int enable;
    int sta_x;
    int sta_y;
    int end_x;
    int end_y;
} line_pos;

typedef struct
{
    area_pos area[2];
    spot_pos spot[2];
    line_pos line;
} image_pos;

如下C函数:

extern "C"{
	void get_struct_array_value(image_pos*  img_data);
}

//函数定义
void get_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 (int i = 0; i < 2; i++){
        printf("area_pos[%d] enable:%d\n",i,img_data->area[i].enable);
        printf("area_pos[%d] x:%d\n",i,img_data->area[i].x);
        printf("area_pos[%d] y:%d\n",i,img_data->area[i].y);
        printf("area_pos[%d] width:%d\n",i,img_data->area[i].width);
        printf("area_pos[%d] height:%d\n",i,img_data->area[i].height);
    }
    for (int j = 0; j < 2; j++){
        printf("spot_pos[%d] enable:%d\n",j,img_data->spot[j].enable);
        printf("spot_pos[%d] x:%d\n",j,img_data->spot[j].x);
        printf("spot_pos[%d] y:%d\n",j,img_data->spot[j].y);
    }
}

JNA代码:

import com.sun.jna.*;
import java.util.Arrays;
import java.util.List;

public class Test {
    public interface CLibrary extends Library {

        CLibrary INSTANCE = (CLibrary) Native.loadLibrary("/libJNADEMO.so", CLibrary.class);


        public static class AREAPOS extends Structure{
            public int enable;
            public int x;
            public int y;
            public int width;
            public int height;

            public static class ByReference extends AREAPOS implements Structure.ByReference{};
            public static class ByValue extends AREAPOS implements Structure.ByValue{};

            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"enable","x","y","width","height"});
            }
        }

        public static class SPOTPOS extends Structure{
            public int enable;
            public int x;
            public int y;

            public static class ByReference extends SPOTPOS implements Structure.ByReference{};
            public static class ByValue extends SPOTPOS implements  Structure.ByValue{};
            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"enable","x","y"});
            }
        }

        public static class LINEPOS extends Structure{
            public int enable;
            public int sta_x;
            public int sta_y;
            public int end_x;
            public int end_y;

            public static class ByReference extends LINEPOS implements Structure.ByReference{};
            public static class ByValue extends LINEPOS implements  Structure.ByValue{};
            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"enable","sta_x","sta_y","end_x","end_y"});
            }
        }

        //模拟结构体数组
        public static class IMAGEPOS extends Structure{
            public AREAPOS.ByValue[] area = new AREAPOS.ByValue[2];
            public SPOTPOS.ByValue[] spot = new SPOTPOS.ByValue[2];
            public LINEPOS.ByValue line;

            public static class ByReference extends IMAGEPOS implements Structure.ByReference{};
            public static class ByValue extends IMAGEPOS implements Structure.ByValue{};
            @Override
            protected List getFieldOrder(){
                return Arrays.asList(new String[] {"area","spot","line"});
            }
        }


        //C函数声明
        void get_struct_array_value(IMAGEPOS.ByReference img);

    } // interface

    public static void main(String[] args) {
        CLibrary.AREAPOS.ByValue abv1 = new CLibrary.AREAPOS.ByValue();
        abv1.enable = 1;
        abv1.x = 10;
        abv1.y = 20;
        abv1.height = 1080;
        abv1.width = 1920;

        CLibrary.AREAPOS.ByValue abv2 = new CLibrary.AREAPOS.ByValue();
        abv2.enable = 0;
        abv2.x = 20;
        abv2.y = 10;
        abv2.height = 1920;
        abv2.width = 1080;

        CLibrary.SPOTPOS.ByValue sp1 = new CLibrary.SPOTPOS.ByValue();
        sp1.enable = 0;
        sp1.x = 1;
        sp1.y = 1;

        CLibrary.SPOTPOS.ByValue sp2 = new CLibrary.SPOTPOS.ByValue();
        sp2.enable = 1;
        sp2.x = 2;
        sp2.y = 2;

        CLibrary.LINEPOS.ByValue line = new CLibrary.LINEPOS.ByValue();
        line.enable = 0;
        line.end_x = 10;
        line.end_y = 20;
        line.sta_x = 30;
        line.sta_y = 40;

        CLibrary.IMAGEPOS.ByReference img = new CLibrary.IMAGEPOS.ByReference();
        img.area[0] = abv1;
        img.area[1] = abv2;
        img.spot[0] = sp1;
        img.spot[1] = sp2;
        img.line = line;
        CLibrary.INSTANCE.get_struct_array_value(img);
    }
}

运行结果:
在这里插入图片描述

2.2 用作输出

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

typedef struct
{
	int enable;
	int max_temp;
	int max_temp_x;
	int max_temp_y;
	int min_temp;	
	int min_temp_x;
	int min_temp_y;	
	int ave_temp;
} area_temp;

typedef struct
{
	int enable;
	int temp;
} spot_temp;

typedef struct
{
	int enable;
	int max_temp;
	int max_temp_x;
	int max_temp_y;
	int min_temp;
	int min_temp_x;
	int min_temp_y;
	int ave_temp;
} line_temp;

typedef struct
{
	int max_temp;
	int max_temp_x;
	int max_temp_y;
	int min_temp;
	int min_temp_x;
	int min_temp_y;
} globa_temp;

typedef struct
{
	area_temp area[6];
	spot_temp spot[6];
	line_temp line;
	globa_temp globa;
} image_temp;

C函数声明:

extern "C" {
	int sdk_get_all_temp_data(const char* ip, image_temp* all_data);
}

PS:此处用到的是第三方sdk的so,函数定义就没有了,只做参考用。
area_temp、spot_temp、line_temp、globa_temp结构体参考章节1中的写法,此处只写了复杂的结构体在JNA中的写法,嵌套的结构体数组JNA代码如下:

import com.sun.jna.Structure;
import java.util.Arrays;
import java.util.List;

public class ImageTemp extends Structure {
    public AreaTemp.ByValue[] area = new AreaTemp.ByValue[6];
    public SpotTemp.ByValue[] spot = new SpotTemp.ByValue[6];
    public LineTemp.ByValue line = new LineTemp.ByValue();
    public GlobaTemp.ByValue globa = new GlobaTemp.ByValue();

    public static class ByReference extends ImageTemp implements Structure.ByReference{}
    public static class ByValue extends ImageTemp implements Structure.ByValue{}

    @Override
    protected List getFieldOrder(){
        return Arrays.asList("area","spot","line","globa");
    }
}

测试代码:

@Test
public void sdkGetAllTempDataTest(){
	A8SDK sdk = new A8SDK();
	ImageTemp.ByReference itbr = new ImageTemp.ByReference();
	int size = itbr.size();
	System.out.println("size="+size);


	AreaTemp.ByValue atbv = new AreaTemp.ByValue();
	SpotTemp.ByValue stbv = new SpotTemp.ByValue();
	itbr.area[0] = atbv;
	itbr.spot[0] = stbv;
	int res = sdk.sdkGetAllTempData("",itbr);
	System.out.println("sdkGetAllTempData res="+res);
	for(int i = 0; i < 6; i++){
		System.out.println("GetAllTempData AreaTemp[" + i + "] enable:" + itbr.area[i].enable);
		System.out.println("GetAllTempData AreaTemp[" + i + "] max_temp:" + itbr.area[i].max_temp);
		System.out.println("GetAllTempData AreaTemp[" + i + "] max_temp_x:" + itbr.area[i].max_temp_x);
		System.out.println("GetAllTempData AreaTemp[" + i + "] max_temp_y:" + itbr.area[i].max_temp_y);
		System.out.println("GetAllTempData AreaTemp[" + i + "] min_temp:" + itbr.area[i].min_temp);
		System.out.println("GetAllTempData AreaTemp[" + i + "] min_temp_x:" + itbr.area[i].min_temp_x);
		System.out.println("GetAllTempData AreaTemp[" + i + "] min_temp_y:" + itbr.area[i].min_temp_y);
		System.out.println("GetAllTempData AreaTemp[" + i + "] ave_temp:" + itbr.area[i].ave_temp);
		System.out.println("GetAllTempData SpotTemp[" + i + "] enable:" + itbr.spot[i].enable);
		System.out.println("GetAllTempData SpotTemp[" + i + "] temp:" + itbr.spot[i].temp);
	}
	System.out.println("GetAllTempData LineTemp enable:" + itbr.line.enable);
	System.out.println("GetAllTempData LineTemp max_temp:" + itbr.line.max_temp);
	System.out.println("GetAllTempData LineTemp max_temp_x:" + itbr.line.max_temp_x);
	System.out.println("GetAllTempData LineTemp max_temp_y:" + itbr.line.max_temp_y);
	System.out.println("GetAllTempData LineTemp min_temp:" + itbr.line.min_temp);
	System.out.println("GetAllTempData LineTemp min_temp_x:" + itbr.line.min_temp_x);
	System.out.println("GetAllTempData LineTemp min_temp_y:" + itbr.line.min_temp_y);
	System.out.println("GetAllTempData LineTemp ave_temp:" + itbr.line.ave_temp);
	System.out.println("GetAllTempData GlobaTemp max_temp:" + itbr.globa.max_temp);
	System.out.println("GetAllTempData GlobaTemp max_temp_x:" + itbr.globa.max_temp_x);
	System.out.println("GetAllTempData GlobaTemp max_temp_y:" + itbr.globa.max_temp_y);
	System.out.println("GetAllTempData GlobaTemp min_temp:" + itbr.globa.min_temp);
	System.out.println("GetAllTempData GlobaTemp min_temp_x:" + itbr.globa.min_temp_x);
	System.out.println("GetAllTempData GlobaTemp min_temp_y:" + itbr.globa.min_temp_y);
}

运行结果如下
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e748dad19459490f9cd64f098e2b7cf1.png
注意:如果没有对结构体数组中第一个元素赋值,会报下面的错
在这里插入图片描述
如果对每一项元素都赋相同的初值,会导致获取到的数组元素值都相同。

3 结构体数组作参数

C函数:

// test.h
struct Person{
    int age;
    char name[20];
};
extern "C"{
	int changeObjs(Person per[], int size);
}


//test.cpp
int changeObjs(Person per[], int size){
    if( size <= 0){
        return -1;
    }
    for (int i = 0; i<size;i++){
        per[i].age *= 10;
        strcpy(per[i].name,"wokettas");
    }

    for(int k=0;k<size;k++){
        printf("person[%d] age:%d\n",k,per[k].age);
        printf("person[%d] name:%s\n",k,per[k].name);
    }
    return 0;
}

JNA代码:

//Person.java
import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.List;

public class Person extends Structure {
    public int age;
    public byte[] name = new byte[20];

    @Override
    protected List getFieldOrder(){
        return Arrays.asList("age","name");
    }
}

Java接口声明:

int changeObjs(Structure per[], int size);

注意:结构体数组做参数时,Java接口中传该结构体本身即可。加上.ByReference或者.ByValue反而不正确

典型错误1–内存不连续

如果在JNA中调用的C函数参数中有结构体数组时,直接new对象会报错
在这里插入图片描述
结构体数组必须使用连续的内存区域。p1,p2都是new出来的对象,不可能连续,用传统方式初始化数组不能解决。查看JNA api发现提供了toArray

public Structure[] toArray(int size)

Returns a view of this structure’s memory as an array of structures. Note that this Structure must have a public, no-arg constructor. If the structure is currently using a Memory backing, the memory will be resized to fit the entire array.(以结构数组的形式返回此结构的内存视图。请注意,此结构必须具有公共的、无参数的构造函数。如果结构当前使用内存备份,则内存将调整大小以适应整个数组。)
使用JNA的toArray产生内存连续的结构体数组:

Person pb = new Person();
Person[] pers = (Person[]) pb.toArray(2);
pers[0].age = 1;
pers[0].name = Arrays.copyOf("k1".getBytes(), 20);
pers[1].age = 2;
pers[1].name = Arrays.copyOf("k2".getBytes(), 20);
int res = CLibrary.INSTANCE.changeObjs(pers, 2);
System.out.println("res="+res);

在这里插入图片描述

典型错误2–误用ByValue

如果在Java接口声明中错误把参数类型写成Person.ByValue,会报java.lang.IndexOutOfBoundsException

// C函数声明
int changeObjs(Person.ByValue per[], int size);
Person.ByValue pb = new Person.ByValue();
Person.ByValue[] pers = (Person.ByValue[]) pb.toArray(2);
pers[0].age = 1;
pers[0].name = Arrays.copyOf("k1".getBytes(), 20);
pers[1].age = 2;
pers[1].name = Arrays.copyOf("k2".getBytes(), 20);
int res = CLibrary.INSTANCE.changeObjs(pers, 2);

运行报错:
在这里插入图片描述
解决方法:将参数类型改为结构体本身即可,即不带ByReference或ByValue。结构体数组做参数时,要区别于非数组的ByReference和ByValue。

4 Java映射C中char[]类型

C中有时候会用char[]传字符串,java中对应的类型为byte[]。可以借助java.util.Arrays类的copyOf ()方法进行转换。
假设有如下C结构体:

typedef struct {
    int enable;
    char ip[20];
} Info;
// C函数声明:
extern "C"{
	void get_info(Info info);
}
// 函数定义
void get_info(Info info){
    printf("enable:%d\n",info.enable);
    printf("ip:%s\n",info.ip);
}

JNA代码:

public static class InfoStruct extends Structure{
public int enable;
public byte[] ip;   // 映射C类型char[]
//public String ip; // 不能直接使用String去映射C类型char[],传参失败


public static class ByReference extends InfoStruct implements Structure.ByReference{};
public static class ByValue extends InfoStruct implements Structure.ByValue{};

@Override
protected List getFieldOrder(){
        return Arrays.asList(new String[] {"enable","ip"});
    }
}

Java调用C函数:
在这里插入图片描述

5 常见问题及其解决方法

参考Java JNA调用C函数常见问题及解决方法一文。
以上就是JNA调用C函数最常用,也是比较复杂的用法了。本篇文章内容较长,希望对你有所帮助,不足之处欢迎指出!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2071542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

scrapy--json结构数据-存储

免责声明:本文仅做演示与分享... 目录 基于命令存储的解析方法: settings.py blibli.py 基于管道存储的解析方法: 1-在爬虫文件中进行数据解析 2-在items.py定义相关属性 3-在 爬虫文件中 把 解析的数据存储封装到item类型对象中 4-把item类型对象提交给管道 5-在管道文件中…

软件设计之MySQL(6)

软件设计之MySQL(6) 此篇应在JavaSE之后进行学习: 路线图推荐&#xff1a; 【Java学习路线-极速版】【Java架构师技术图谱】 Navicat可以在软件管家下载 使用navicat连接mysql数据库创建数据库、表、转储sql文件&#xff0c;导入sql数据 MySQL数据库入门到大牛&#xff0c;my…

【吊打面试官系列-Memcached面试题】memcached 能接受的 key 的最大长度是多少?

大家好&#xff0c;我是锋哥。今天分享关于 【memcached 能接受的 key 的最大长度是多少&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; memcached 能接受的 key 的最大长度是多少&#xff1f; key 的最大长度是 250 个字符。需要注意的是&#xff0c;250 是 m…

KEIL中分散加载文件基础知识

一、分散加载文件基本概念 1、分散加载文件&#xff1a;&#xff08;即scatter file 后缀为.scf&#xff09;是一个文本文件&#xff0c;通过编写一个分散加载文件来指定ARM连接器在生成映像文件时如何分配RO,RW,ZI等数据的存放地址。如果不用分散加载文件指定&#xff0c;那么…

区域形态学demo发布

demo实现了halcon中threshold、connection、fill_up、union、difference、intersection、dilation、erosion、opening、closing等算子功能&#xff0c;区域使用行程编码表示。目前可选择的结构元有圆形、矩形、十字&#xff08;实际接口没有限制&#xff09;&#xff0c;所有结…

Flutter-->Widget上屏之路

本文主要介绍Flutter中创建一个Widget到屏幕上渲染出Widget内容的路程. 拾用本文您将获得: Widget是什么Element是什么RenderObject是什么 附加Buff: Widget直接渲染成图片文本String的绘制图片ui.Image的绘制 这一切都要从runApp方法开始说起, 如果你还不知道runApp是什么…

【非常简单】 猿人学web第一届 第12题 入门级js

这一题非常简单&#xff0c;只需要找到数据接口&#xff0c;请求参数 m生成的逻辑即可 查看数据接口 https://match.yuanrenxue.cn/api/match/12 查看请求对应的堆栈中的 requests 栈 list 为对应的请求参数 list 是由 btoa 函数传入 ‘yuanrenxue’ 对应的页码生成的 bto…

安装torchvision==0.5.0

安装pytorch 1.4 但是在当前配置的镜像源中找不到 torchvision0.5.0 这个版本的包。 直接找资源下载 网址添加链接描述 直接运行该命令&#xff0c;成功。 然后重复运行上面的命令就可以了 # CUDA 9.2 conda install pytorch1.4.0 torchvision0.5.0 cudatoolkit9.2 -c pyto…

Spring Boot(快速上手)

Spring Boot 零、环境配置 1. 创建项目 2. 热部署 添加依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> </dependency&…

Linux下进程间的通信--消息队列

System V IPC的概念 System V IPC&#xff08;System V Interprocess Communication&#xff09;是Unix和类Unix操作系统中一套传统的进程间通信机制&#xff0c;它包括三种主要的通信方式&#xff1a;消息队列、信号量和共享内存。这些机制提供了一种在不同进程之间交换数据和…

llamaindex+Internlm2 RAG实践 #书生谱语大模型实战营#

1.打卡任务&#xff1a; 本次的打卡任务是llamaindexInternlm2 RAG实践&#xff0c;我们需要基于 LlamaIndex 构建自己的 RAG 知识库&#xff0c;寻找一个问题 A 在使用 LlamaIndex 之前InternLM2-Chat-1.8B模型不会回答&#xff0c;借助 LlamaIndex 后 InternLM2-Chat-1.8B 模…

Axure设计之下拉单选框教程(中继器)

在Axure RP中&#xff0c;使用中继器&#xff08;Repeater&#xff09;可以实现许多复杂而动态的用户界面组件&#xff0c;比如下拉单选框。本文将详细介绍如何通过中继器创建一个美观且功能丰富的下拉单选框。 一、案例预览 预览地址&#xff1a;https://1zvcwx.axshare.com …

如何使用ssm实现基于JAVA的网上药品售卖系统

TOC ssm133基于JAVA的网上药品售卖系统jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规…

什么是堡垒机

堡垒机&#xff0c;即在一个特定的网络环境下&#xff0c;为了保障网络和数据不受来自外部和内部用户的入侵和破坏&#xff0c;而运用各种技术手段监控和记录运维人员对网络内的服务器、网络设备、安全设备、数据库等设备的操作行为&#xff0c;以便集中报警、及时处理及审计定…

鹏城杯 2022 取证writeup

简单取证 我们进去首先使用imageinfo pslist screenshot clipboard filescan 等等插件查看相关信息。 这里找到一个password姑且先留着 然后使用filescan找到了一个jpg文件 我们先dump下来 vol -f file.raw --profileWinXPSP2x86 dumpfiles -Q 0x000000000207e3d8 -D . 然…

Generating Query Recommendations via LLMs 【阅读笔记】

背景 主要去进行query的相关搜索补充&#xff1b; 例如 我们引入生成查询推荐&#xff08;GQR&#xff09;系统。 GQR以大语言模型为基础&#xff0c;利用大语言模型的提示能力&#xff0c;通过提示中提供的几个例子&#xff08;检索或手工&#xff09;来理解推荐任务。 方案…

主机监控与审计系统是什么?这个功能让您的效率翻倍!

天下之事&#xff0c;皆需明察秋毫&#xff0c;方能运筹帷幄&#xff0c;决胜千里。 于信息之海&#xff0c;主机者&#xff0c;犹若疆土之基石&#xff0c;承载着数据之重&#xff0c;运行着系统之脉。 然&#xff0c;世事如棋局局新&#xff0c;网络之域&#xff0c;暗流涌…

惠海H6432 dcdc升压恒压支持IC 3.7V 7.4V升压9V12V15V24V3A大电流 摄影灯光电源

1. 产品描述 H6432是一款电流模式B00ST异步升压恒压控制驱动芯片&#xff0c;适用于2.7-24V输入电压范 围的升压恒压电源应用领域&#xff0c;启动电压低至2. 5V。芯片根据负载的大小自动切换PWM&#xff0c;PFM和BURST模式以提高各个负载端的电源系统效率。芯片通过EN脚实现…

kali2022重置密码

在如下系统选择界面&#xff0c;按‘E’&#xff0c; 进入到编辑界面&#xff0c;将“ro quiet”修改为“rw init/bin/bash”。修改完成后ctrl X保存编辑并继续引导ctrlx进行引导&#xff0c;passwd修改密码&#xff0c;成功后重启&#xff0c;用root和新密码登录。

Adversarial Diffusion Distillation

sd turbohttps://static1.squarespace.com/static/6213c340453c3f502425776e/t/65663480a92fba51d0e1023f/1701197769659/adversarial_diffusion_distillation.pdf#page5.83https://github.com/Stability-AI/generative-models 问题引入 1-4 steps fast diffusion model samp…