[英]How to pass a pointer to a struct array to a function in java using JNA?
[英]JNA (Java): How to pass an array of pointers to struct?
我正在使用JNA从Java调用C库。
在我的C代码中,我有:
void printStructArray( SomeStruct **someStruct, int arraySize );
这需要一个指向struct的指针数组,即该方法执行此操作:
void printStructArray( SomeStruct **someStruct, int arraySize ) {
for( int i = 0; i < arraySize; i++ ) {
cout << "someStruct: " << someStruct[i]->aLong << " " << someStruct[i]->aString << " " << someStruct[i]->aDouble << endl;
}
}
这只是一个玩具示例,但我有一个我想要谈论的实际库需要相同类型的参数,但我认为使用玩具示例在这里更容易解释?
我已经尝试了各种各样的东西,但我不知道如何(i)在JNA中声明这个函数(ii)在JNA中调用这个函数。
我的最新(失败)尝试是:
SomeStruct.byReference[] structs = new SomeStruct.byReference[]{
new SomeStruct.byReference(123,"hey!",1.23),
new SomeStruct.byReference(456,"cool!",1.45),
new SomeStruct.byReference(789,"world!",1.67) };
PointerByReference pointerByReference = new PointerByReference(structs[0].getPointer());
JniTest.instance.printStructArray(pointerByReference, 3);
这会导致SIGSEGV。
或者:
SomeStruct.byReference[] structs = (SomeStruct.byReference[]) new SomeStruct().toArray( new SomeStruct.byReference[]{
new SomeStruct.byReference(123,"hey!",1.23),
new SomeStruct.byReference(456,"cool!",1.45),
new SomeStruct.byReference(789,"world!",1.67) } );
PointerByReference pointerByReference = new PointerByReference(structs[0].getPointer());
JniTest.instance.printStructArray(pointerByReference, 3);
这会导致ArrayStoreException
试过这个:
SomeStruct.byReference[] structs = new SomeStruct.byReference[]{
new SomeStruct.byReference(123,"hey!",1.23),
new SomeStruct.byReference(456,"cool!",1.45),
new SomeStruct.byReference(789,"world!",1.67) }; JniTest.instance.printStructArray(structs, 3);
方法声明为:
void printStructArray(SomeStruct.byReference[] someStructarray, int num);
这给了'0'作为函数的输出,虽然好点是它不会崩溃,但它也没有给出正确的行为。
思考?
传递Structure.ByReference数组就足够了; 数组的地址传递给本机代码。 JNA自动为指针数组分配空间,在函数调用后超出范围。
PointerByReference旨在通过引用传递指针值(即被调用者可以改变该值)。 这不是在这种情况下适当的。
我刚刚找到了一个非常好的解决方案,即使用BridJ而不是JNA。 也许有办法让JNA正常工作,但这似乎并不明显。 BridJ真的很容易使用:
宣言:
public static native void printStructArray(Pointer<Pointer<SomeStruct > > someStruct, int arraySize);
用法:
Pointer<Pointer<SomeStruct>> pointers = Pointer.allocatePointers(SomeStruct.class, 3);
pointers.set(0, Pointer.pointerTo( new SomeStruct().aDouble(1.58).aLong(5432).aString(Pointer.pointerToCString("Wheee!")) ) );
pointers.set(1, Pointer.pointerTo( new SomeStruct().aDouble(1.58).aLong(5432).aString(Pointer.pointerToCString("Wheee!")) ) );
pointers.set(2, Pointer.pointerTo( new SomeStruct().aDouble(1.58).aLong(5432).aString(Pointer.pointerToCString("Wheee!")) ) );
JnitestLibrary.printStructArray(pointers, 3 );
看起来他们不支持按值的结构,但是我当前的界面中没有任何值的结构,所以这对我来说不是问题。 显然性能还可以,但我没有亲自测试性能。
请注意,我仍然对JNA解决方案持开放态度,并且会勾选任何能够为我提供JNA解决方案的人。
这是C还是C ++?
如果是C,为什么不简单地使用calloc / malloc为结构分配双指针如下?
somestruct = (SomeStruct **)calloc(arraySize, sizeof(SomeStruct *));
for (i = 0; i < arraySize; i++)
somestruct[i] = (SomeStruct *)calloc(1, sizeof(SomeStruct));
现在,您可以根据需要填充结构。
最后,我从来没有找到一个有效的解决方案。 我所做的是通过在C中编写一个包装器接口来解决这个问题,它提供了一个非常简单的Java接口,然后很容易链接到使用JNA,而不需要Pointer等等。 这非常有效,并且比努力使Pointer工作更省力。
所以,我的界面看起来像:
int createHandle()
void doSomething( int handle )
void releaseHandle( int handle)
在时间方面,尝试创建一些超级复杂的jna实现以直接连接到底层c接口似乎需要花费很少的努力。
另一个优点是这意味着它很容易连接到c ++库,因为这样,c ++接口由ac接口包装,易于连接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.