Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 结构包含char的内存访问无效*_Java_Structure_Jna - Fatal编程技术网

Java 结构包含char的内存访问无效*

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[] = &

我正在尝试使用JNA映射一个包含一些
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();
  • 关于char*类型,我用字符串替换了指针,但我遇到了同样的问题
  • 一旦我检索到作为指针的fileName项,我如何获取fileName引用的值?是不是
    err.errorDetails.fileName.getString(0)
  • 因此,我尝试隔离每种类型的结构,并创建了以下C函数作为示例:

    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。 标签界面