【问题标题】:How do I make JNI method call not static when using native C++ objects?使用本机 C++ 对象时,如何使 JNI 方法调用不是静态的?
【发布时间】:2013-02-10 20:59:59
【问题描述】:

我有以下 JNI 包装器 C++ 代码:

#include "map_container.h"
extern "C" {
    JNIEXPORT void JNICALL Java_com_map_Map_openMapNative(JNIEnv* env, jobject thiz, jstring path);
};

static map_container* map = NULL;

void Java_com_map_Map_openMapNative(JNIEnv* env, jobject thiz, jstring path)
{
  const char* filename_utf8 = env->GetStringUTFChars(path, false);

  if ( mapview )
  {
    delete mapview;
    mapview = NULL;
  }

  mapview = new map_container((char*)filename_utf8);

  if (filename_utf8)
  {
    env->ReleaseStringUTFChars(path, filename_utf8);
  }
}

并将com.map.Map.openMapNative 声明为静态,这意味着我可以一次操作一张地图。如何修改此 C++ 代码以使 map_container* map 变为非静态并属于 com.map.Map 类的确切实例? map_container 完全是 C++ 类,在 Java 中没有反射。

【问题讨论】:

    标签: android java-native-interface android-ndk


    【解决方案1】:

    我正在使用SWIG 来生成所有必要的包装代码。您只需定义要包装在接口定义文件中的类和函数,然后让 SWIG 为您创建所有必需的 C++ 和 Java 代码。强烈推荐!恕我直言,手工编写 JNI 代码太无聊且容易出错。请参阅 SWIG docs for Java,它非常易于使用。

    【讨论】:

    • 感谢您提供很棒的链接。我不确定我是否会使用 SWIG,但它的文档包含很好的示例和正确执行我的任务的解释。
    【解决方案2】:

    如果您在 Java 源代码中已将 Map.openMapNative 声明为“静态原生”,那么当前声明具有误导性,因为第二个参数实际上是对 Map 类的引用(应该是“jclass clazz”而不是“jobject这”)。没关系,因为您没有使用“thiz”,并且每个 jclass 都是一个作业。

    使这个非静态的方法是从 Java 端的声明中删除“静态”,并开始使用“thiz”来访问实例的成员。

    【讨论】:

    • 谢谢,但是如何让map_container 成为thiz 的成员?
    • 将 C++ 对象嵌入到 Java 对象中可以通过在 Java 源代码中声明一个 int 或(对于 64 位指针)long 字段,然后使用 SetIntField 设置该字段来完成。在 openMapNative 中,您将使用 GetIntField 来恢复指针。丑陋的部分是处理对象的生命周期,例如您可能需要在 Java 端声明一个终结器,该终结器调用删除 C++ 对象的清理函数。
    【解决方案3】:

    可能有点晚了,但这本食谱非常宝贵!

    http://thebreakfastpost.com/2012/01/23/wrapping-a-c-library-with-jni-part-1/

    乍一看,根据您的需要,SWIG 可能是超杀伤力!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      • 2012-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      相关资源
      最近更新 更多