JNA:从指向结构指针的指针获取值
JNA : Get value from a pointer to a pointer to a structure
关于指向指针的指针问题,我在使用 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
}
我的步骤有什么错误吗?
当您收到“无效内存访问”错误时,您应该开始查看本机内存分配何时完成。通常 API 记录(并告诉您如何释放它),如果没有,您知道这是您的责任。在这种情况下,您可以在发布的 C 代码中看到,分配是在测试方法内部完成的:
PA current = (PA) malloc(sizeof(A));
和
PA next = (PA) malloc(sizeof(A));
这里的问题是 Java 方不知道该分配,因此您必须手动进行。
您使用 PointerByReference
的函数映射看起来不错。虽然您可以在 return 上使用 getInt(0)
,但此时您最好只从 returned 指针实例化 A
结构,就像您所做的那样:
A a = new A(pointer.getValue());
那么 a.num
应该是您预期的 123321。然后您必须使用 returned 指针(指向本机分配的 link)并使用它来创建另一个 Java端结构:
A b = new A(a.next);
(您可能只想在结构中使用 Pointer
以简化该部分。如果您使用 ByReference
或 A.ByReference
,则在此使用 getPointer()
部分。)
至此,我相信b.num
应该给你456。
关于指向指针的指针问题,我在使用 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
}
我的步骤有什么错误吗?
当您收到“无效内存访问”错误时,您应该开始查看本机内存分配何时完成。通常 API 记录(并告诉您如何释放它),如果没有,您知道这是您的责任。在这种情况下,您可以在发布的 C 代码中看到,分配是在测试方法内部完成的:
PA current = (PA) malloc(sizeof(A));
和
PA next = (PA) malloc(sizeof(A));
这里的问题是 Java 方不知道该分配,因此您必须手动进行。
您使用 PointerByReference
的函数映射看起来不错。虽然您可以在 return 上使用 getInt(0)
,但此时您最好只从 returned 指针实例化 A
结构,就像您所做的那样:
A a = new A(pointer.getValue());
那么 a.num
应该是您预期的 123321。然后您必须使用 returned 指针(指向本机分配的 link)并使用它来创建另一个 Java端结构:
A b = new A(a.next);
(您可能只想在结构中使用 Pointer
以简化该部分。如果您使用 ByReference
或 A.ByReference
,则在此使用 getPointer()
部分。)
至此,我相信b.num
应该给你456。