通过JNI高效地传递大型C结构体

3
我有一个大的C结构体(约40个成员,包括int和char[]),我需要通过JNI传递到Java端进行进一步处理。这会反复发生。(我已经将GetMethodID()等放入C端的init()函数中,因此我只需要调用它们一次。)
有什么有效的方法可以做到这一点吗?
我能想到以下几种方法:
1. 通过GetMethodID( ..., "<init>", ... )实例化一个具有相应成员的Java类,并通过构造函数传递C结构的所有成员; 2. 分配一个具有相应成员的Java结构体,并通过SetXYZField()初始化(公共)成员; 3. ...
我有遗漏什么吗?(这是我第一次与JNI打交道。)是否真的没有有效的方法来“同步”C结构体和Java结构体?
哪种传递方法更有效,1还是2?在1的情况下,我应该通过CallXYZMethod()(参数列表)还是CallXYZMethodA()(参数数组)传递构造函数参数?
谢谢您的回复。
编辑:稍微改了一下措辞;2当然不需要是一个类,如果有其他处理C数据的解决方案,则在Java端不严格需要一个结构体。
编辑2:我是用C++做的,但是结构体本身来自于一个C链接回调函数,即对问题没有任何特定于C ++的内容。重新表述为“C”而不是“C ++”。
2个回答

1

很抱歉我没有时间写一个深入的答案或进一步研究,但是一段时间以前,我不得不与JNI做了相当多的工作,并发现使用SWiG非常有帮助。我不确定它的效率,但我想它会生成相当有效的代码。

无论如何,请查看SWiG,其中有关于按值传递结构体和主要的结构体的一些内容。

祝你好运。


1
我宁愿不涉足另一项技术或第三方源码,特别是因为我首先需要了解SWIG。但是我已经把它放在我的阅读列表上,谢谢! - DevSolar

1

为了纯粹的效率,最好尽量减少通过JNI进行的调用,因此最好选择通过选项1将所有数据发送并创建一个新对象。

如果您想避免每次更新分配新对象,则可以在Java这一侧拥有一个“recieveUpdate(... 40个参数 ...)”方法,尽管这是一个令人不满的设计。


谢谢你提醒我JNI调用的数量问题。这个我应该自己想到的。由于这是一个异步回调的事情,每次调用我需要在Java端创建一个新对象,否则我会陷入深度多线程的麻烦中。;-) - DevSolar
1
哦,祝你好运。希望你已经知道了,但是JNI文档很糟糕,所以请确保方法ID等仅在缓存它们的线程中使用,并且如果使用本地线程,请调用AttachCurrentThread。 - MHarris
天哪!谢谢!当然,我假设静态缓存JNIEnv、jclass和jmethodID一次,并在回调函数中使用缓存的值是可以的。所以你的意思是,每次调用我的注册为回调的C函数时,我都必须重新获取JNIEnv等?真烦人... - DevSolar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接