我正试图绘制一个包含一些 char *
使用jna的字段。我得到以下例外:
线程“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代码:
public interface IFunctions extends Library {
public static class ERR_DETAILS extends Structure {
public static class ByValue extends ERR_DETAILS implements Structure.ByValue {}
public static class ByReference extends ERR_DETAILS implements Structure.ByReference {}
public Pointer fileName;
public Pointer message;
public int lineNumber;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "fileName", "message","lineNumber"});
}
}
public static class ERR_CODE {
public static int OK = 0;
public static int ERR_ONE = 1;
public static int ERR_TWO = 2;
public static int ERR_THREE = 3;
public static int ERR_FOUR = 4;
public static int ERR_FIVE = 5;
public static int ERR_SIX = 6;
}
public static class ERR extends Structure {
public static class ByValue extends ERR implements Structure.ByValue {}
public static class ByReference extends ERR implements Structure.ByReference {}
public ERR_CODE errorCode;
public ERR_DETAILS errorDetails;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "errorCode", "errorDetails"});
}
}
public ERR ErrorTest();
}
下面是我的java测试主类:
ERR err = IFunctions.ErrorTest();
关于char*类型,我用字符串替换了指针,但得到了相同的问题。
一旦我以指针的形式检索到filename项,如何获取filename引用的值?它是 err.errorDetails.fileName.getString(0);
?
因此,我尝试隔离每种类型的结构,并创建了以下c函数作为示例:
签名:
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\u代码
我忘了关于枚举类型定义的一些想法了吗?
2条答案
按热度按时间qojgxg4l1#
问题出在你的Map上
ERR_CODE
枚举。jna没有
enum
类型,因为这些类型通常是32位整数。但是,您已经将它Map为一个普通java类(扩展对象),它没有任何jnaMap。传统的Map绘制方法
enum
在jna中,是将int值 Package 在interface
. (这只是用于自文档化代码。实际上,你真正需要的是int
值。)所以你应该改变主意
ERR_CODE
Map到:注意
public
以及static
修改器对于接口成员是多余的。那你也该换衣服了
ERR
结构Map到:注意,我刚刚绘制了
enum
作为一个int
,使用注解字段表示int
代表。这里有一个潜在的对齐问题,它可能依赖于平台。通常最大字节大小用于对齐,因为
ERR_DETAILS
Map中包含8字节指针,4字节int和下一个元素的字节边界之间可能不对齐(例如。,errorDetails
可以从偏移量开始0x8
而不是0x4
. 要解决此问题,可能需要在结构中设置对齐类型,将Map更改为:另外,我还删除了不必要的
ByValue
以及ByReference
子类。你很少需要在结构内部定义这些,ByValue
是默认的和in方法参数ByReference
是默认值,您只需要在很少的情况下定义这些值,而不使用默认值。我还使用了jna 5.x
@FieldOrder
而不是重写方法。你可以用
String
在的结构Map中char *
而不是Pointer
,尽管Pointer
以及getString()
如果您选择保留Map,则是正确的处理方法:xcitsw882#
最后我得到了对我的问题的回应。
在我的jna Package 器中,我必须显式地定义我的函数按值返回结构,而不是按引用返回结构,因为jna默认是这样做的。正如jnaapi中关于结构类的描述:“当用作函数参数或返回值时,这个类对应于struct*。当用作另一个结构中的字段时,它对应于struct。标记接口structure.byreference和structure.byvalue可用于更改默认行为。“
因此,解决方案如下:
没有什么可以改变的。谢谢你的帮助。