Java 结构包含char的内存访问无效*
我正在尝试使用JNA映射一个包含一些Java 结构包含char的内存访问无效*,java,structure,jna,Java,Structure,Jna,我正在尝试使用JNA映射一个包含一些char*字段的结构。我得到以下例外情况: 线程“main”java.lang中出现异常。错误:内存访问无效 这是我的C代码: 调用的函数的签名 extern“C”MATHLIBRARY_API ERR ErrorTest(); 以我所做的C示例实现为例: ERR sngErrorTest() { ERR err; char message[] = "My message"; char filename[] = &
char*
字段的结构。我得到以下例外情况:
线程“main”java.lang中出现异常。错误:内存访问无效
这是我的C代码:
调用的函数的签名
extern“C”MATHLIBRARY_API ERR ErrorTest();
以我所做的C示例实现为例:
ERR sngErrorTest() {
ERR err;
char message[] = "My message";
char filename[] = "My file Name";
err.errorCode = OK;
err.errorDetails.fileName = NULL;
err.errorDetails.lineNumber = 1;
err.errorDetails.message = message;
err.errorDetails.fileName = filename;
return err;
}
C类型定义:
typedef enum {
OK = 0,
ERR_ONE,
ERR_TWO,
ERR_THREE,
ERR_FOUR,
ERR_FIVE,
ERR_SIX,
} ERR_CODE;
typedef struct {
char *fileName;
char *message;
int lineNumber;
} ERR_DETAILS;
typedef struct {
ERR_CODE errorCode;
ERR_DETAILS errorDetails;
} ERR;
以下是我的java代码:
公共接口IFunctions扩展库{
公共静态类ERR_DETAILS扩展结构{
公共静态类ByValue扩展ERR_DETAILS实现Structure.ByValue{}
公共静态类ByReference扩展了ERR_细节实现结构。ByReference{}
公共指针文件名;
公共指针消息;
公共整数行号;
@凌驾
受保护列表getFieldOrder(){
返回Arrays.asList(新字符串[]{“fileName”、“message”、“lineNumber”});
}
}
公共静态类错误代码{
公共静态int OK=0;
公共静态int ERR_ONE=1;
公共静态int ERR_TWO=2;
公共静态int ERR_三=3;
公共静态int ERR_FOUR=4;
公共静态输入错误=5;
公共静态整数误差=6;
}
公共静态类ERR扩展结构{
公共静态类ByValue extends ERR实现Structure.ByValue{}
公共静态类ByReference扩展了ERR实现结构。ByReference{}
公共错误代码错误代码;
公共错误详细信息错误详细信息;
@凌驾
受保护列表getFieldOrder(){
返回Arrays.asList(新字符串[]{“errorCode”,“errorDetails”});
}
}
公共错误测试();
}
以下是我的java测试主类:
ERR err = IFunctions.ErrorTest();
err.errorDetails.fileName.getString(0)代码>
ERR_CODE errCode = IFunctions.ErrorCode();
签名:
extern "C" MATHLIBRARY_API ERR_CODE ErrorCode();
C执行:
ERR_CODE ErrorCode() {
ERR_CODE err_code;
err_code = OK;
return err_code;
}
Java声明
public interface IFunctions extends Library {
....
public ERR_CODE ErrorCode();
....
}
调用我的jna函数:
ERR_CODE errCode = IFunctions.ErrorCode();
在这种情况下,我会得到以下错误:
线程“main”java.lang.IllegalArgumentException中的异常:函数ErrorCode中不支持的返回类型类ERR_代码
我是否忘记了有关枚举类型定义的一些想法?问题在于您对
ERR\u code
enum的映射
JNA没有enum
类型的直接映射,因为这些类型通常是32位整数。但是,您已经将其映射为一个普通java类(扩展对象),它没有任何JNA映射
在JNA中映射enum
的传统方法是将int值包装在接口中。(这只是用于自文档化代码。实际上,您真正需要的只是int
值。)
因此,您应该将ERR\u code
映射更改为:
接口错误代码{
int OK=0;
int ERR_ONE=1;
int ERR_TWO=2;
int ERR_三=3;
int ERR_FOUR=4;
int ERR_五=5;
int ERR_六=6;
}
注意,public
和static
修饰符对于接口成员是多余的
然后,还应将ERR
结构映射更改为:
@FieldOrder({“errorCode”,“errorDetails”})
类ERR扩展了结构{
public int errorCode;//错误代码
公共错误详细信息错误详细信息;
}
注意:我刚刚将enum
映射为int
,使用注释字段表示int
表示的特定类型(enum)
这里有一个潜在的对齐问题,它可能依赖于平台。通常,最大字节大小用于对齐,并且由于ERR_DETAILS
映射中包含8字节指针,因此4字节int与下一个元素的字节边界之间可能存在不对齐(例如,errorDetails
可能从偏移量0x8
开始,而不是0x4
开始。要解决此问题,您可能需要在结构中设置对齐类型,将映射更改为:
@FieldOrder({“errorCode”,“errorDetails”})
类ERR扩展了结构{
public int errorCode;//错误代码
公共错误详细信息错误详细信息;
公共错误(){
超级();
setAlignType(对齐\无);
}
}
另外请注意,我还删除了不必要的ByValue
和ByReference
子类。您很少需要定义这些子类——在结构中,ByValue
是默认值,在方法参数中ByReference
是默认值,您只需要在很少不使用默认值的情况下定义它们。
我还使用了JNA 5.x@FieldOrder
注释,而不是重写该方法
您可以在char*
的结构映射中使用String
,而不是Pointer
,尽管指针
和getString()
是处理这些映射的正确方法,如果您选择保持该映射:
@FieldOrder({“文件名”、“消息”、“行号”})
类错误详细信息扩展了结构{
公共字符串文件名;
公共字符串消息;
公共整数行号;
}
我终于得到了对我的问题的回应
在我的JNA包装器中,我必须明确定义我的函数按值返回结构,而不是按引用返回结构,因为JNA默认情况下是这样做的。
如JNA API中关于结构类的描述:
当用作函数参数或返回值时,此类对应于struct*。
当用作另一个结构中的字段时,它对应于struct。
标签界面