【问题标题】:JNA : Get value from a pointer to a pointer to a structureJNA:从指向结构的指针中获取值
【发布时间】:2020-07-14 15:20:17
【问题描述】:

JNA 遇到了关于指针指针问题的问题。

示例结构:

typedef struct _A {
    unsigned int num;
    struct _A *next;
} A, *PA;

C方法:

void test(PA *a) {
    PA current = (PA) malloc(sizeof(A));
    current->num = 123321;

    PA next = (PA) malloc(sizeof(A));
    next->num = 456;
    current->next = next;

    *a = current;
}

一个简单的C语言测试:

int main() {
    PA a = NULL;
    test(&a);

    printf("%d\n", a->num);
    printf("%d", a->next->num);
}

JNA 代码

public interface DLLLibrary extends Library {
    ......

    void test(PointerByReference a);
}

public class A extends Structure {
    public int num;
    public ByReference next;
    public A() {
        super();
    }
    protected List<String> getFieldOrder() {
        return Arrays.asList("num", "next");
    }

    public A(Pointer peer) {
        super(peer);
    }
    public static class ByReference extends A implements Structure.ByReference { }
    public static class ByValue extends A implements Structure.ByValue { }
}

最后,我试图获取在 C 中更新的结构字段,但得到“无效的内存访问”

public static void main(String[] args) {
    PointerByReference pointer = new PointerByReference();
    DLLLibrary.INSTANCE.test(pointer);

    assert pointer.getValue().getInt(0) == 123321; //this works
    A a = new A(pointer.getValue());
    //assert a.next.num == 456;  //excepted action
    a.read(); //java.lang.Error: Invalid memory access
}

我的步骤有什么错误吗?

【问题讨论】:

    标签: java pointers jna


    【解决方案1】:

    当您收到“无效内存访问”错误时,您应该开始查看本机内存分配何时完成。通常 API 记录(并告诉您如何释放它),如果没有,您知道这是您的责任。在这种情况下,您可以在您发布的 C 代码中看到,分配是在测试方法内部完成的:

    PA current = (PA) malloc(sizeof(A));
    

    PA next = (PA) malloc(sizeof(A));
    

    这里的问题是 Java 端不知道该分配,因此您必须手动进行。

    您使用PointerByReference 的函数映射看起来不错。虽然您可以在返回时使用 getInt(0),但此时您最好只从返回的指针中实例化 A 结构,就像您所做的那样:

    A a = new A(pointer.getValue());
    

    那么a.num 应该是您预期的 123321。然后您必须获取返回的指针(指向本地分配的链接)并使用它来创建另一个 Java 端结构:

    A b = new A(a.next);
    

    (您可能只想在结构中使用Pointer 以简化该部分。如果您使用ByReferenceA.ByReference,则在此部分使用getPointer()。)

    在这一点上,我相信b.num应该给你456。

    【讨论】:

    • 嘿@Daniel Widdis,非常感谢您帮助我,您指出的原因是合理的,但修复步骤同样不起作用。 1. 当我将映射更改为``` void test(A a)``` 时,A.num 指向随机数,next 字段得到null
    • 嗯。不知道为什么它不起作用。本机代码正在分配内存,但 Java 端没有看到它。有几种方法可以使这项工作。你能发布你更新的代码吗?
    • 可以在gist看到修改后的java代码
    • 谢谢。好的,这是一个非常不寻常的 API。我想我建议发送一个结构是错误的,认为它会填充它。事实上,您必须发送一个裸指针(通过引用),因为本机代码进行分配。所以我想你之前的代码是正确的指针/ getInt 部分。新的 A() 部分也可能很好。我认为您需要对从 Next 检索到的指针执行另一个 new A()。让我完全重写我的答案....
    • 行得通,谢谢。我需要将ByReference 字段更改为Pointer 以避免读取无效内存,因为我没有在C 中将next-&gt;next 的值设置为NULL
    猜你喜欢
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 2011-09-15
    相关资源
    最近更新 更多