【问题标题】:Passing large C structure through JNI efficiently通过 JNI 有效地传递大型 C 结构
【发布时间】:2009-10-15 09:08:52
【问题描述】:

我有一个大型 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.当然不需要是类,如果Java端有其他处理C数据的解决方案,我也不需要Java端的struct。

编辑 2: 我在 C++ 中执行此操作,但结构本身源于 C 链接回调函数,即没有特定于 C++ 的问题。改写为“C”而不是“C++”。

【问题讨论】:

    标签: java c java-native-interface


    【解决方案1】:

    为了纯粹的效率,最好尽量减少通过 JNI 的调用,所以最好的办法是通过选项 1 发送所有数据并创建一个新对象。

    如果您想避免每次更新分配一个新对象,您也可以在 Java 端使用“recieveUpdate(...40 params ...)”方法,尽管它的设计令人畏惧。

    【讨论】:

    • 感谢有关 JNI 调用次数的提示。我自己应该想到的。由于这是一个异步回调,每次调用我都需要在 Java 端创建一个新对象,否则我会陷入深度多线程问题。 ;-)
    • 哦,祝你好运。希望您已经知道这一点,但是 JNI 文档令人震惊:确保方法 ID 等仅在缓存它们的线程中使用,如果使用本机线程,请调用 AttachCurrentThread。
    • 你们这些翻天覆地的神!谢谢!当然,我假设静态缓存 JNIEnv、jclass 和 jmethodID 一次并在回调函数中使用缓存的值就可以了。所以你的意思是,每次我的注册回调 C 函数之一被调用时,我都必须重新检索 JNIEnv 等?噗噗……
    【解决方案2】:

    很抱歉,我没有时间写一个深入的答案或进一步研究这个问题,但不久前我不得不用 JNI 做很多工作,我发现使用 SWiG 有很大帮助。我不确定它的效率,但我想它会生成非常高效的代码。

    不管怎样,看看SWiGPassing structures by value 和主要的Structures 有一点。

    祝你好运。

    【讨论】:

    • 我宁愿不采用其他技术/第三方来源,尤其是因为我必须先阅读 SWIG。但我把它放在我的阅读清单上,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-05-12
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    • 2015-11-14
    相关资源
    最近更新 更多