7

我有一个必须在现有 Android 实现中使用的 C++ 库。我正在使用 Android NDK 并通过 JNI 使用 C++ 类。

但是,我无法找到如何使用 JNI 在 Java 中对 C++ 抽象类进行子类化。

我面临的问题:我的目标是通过继承抽象 C++ 类为 C++ 中的虚拟方法提供 Java 实现。我已经加载了本机库,并且正在尝试声明本机方法。C++ 方法有关键字'virtual'。当我在加载 C++ 库后在 Java 中声明本机函数时,无法识别“虚拟”。这里有什么问题?

任何帮助表示赞赏。我是 JNI 的新手。提前致谢。

4

1 回答 1

7

假设我们有一个 C++ 类:

class iVehicle
{
public:
   virtual void Run() {}; // not-pure virtual here for simplicity of a wrapper, but could be pure (see the end of the post)
   virtual int  GetSize() const; // we want to reuse it in Java
};

我们想在 Java 中创建一个类,该类在调用调用 C++ 代码的意义上Bot扩展类,并且从 C++ 的角度来看,我们可以将 的实例用作变量。这很难,因为 C++ 没有为反射提供好的内置功能。iVehiclesuperiVehicle::GetSize()BotiVehicle*

这是一种可能的解决方案。

要在 Java 中使用 C++ 类,我们需要生成一个 Java 包装器,即:

class iVehicle
{
   public void Run() { Native_Run(); }
   public int  GetSize() { return Native_GetSize(); }

   private native void Native_Run();
   private native int  Native_GetSize();

   // typecasted to pointer in C++
   private int NativeObjectHolder;

   // create C++ object
   native static private int CreateNativeObject();
}

Java中的用法很简单:

class Bot extends iVehicle
{
   public int GetSize()
   {
      if ( condition ) return 0;

      // call C++ code
      return super.GetSize();
   }
}

但是,此代码有 C++ 部分:

static jfieldID gNativeObjectHolderFieldID;

JNIEXPORT void JNICALL Java_com_test_iVehicle_Run( JNIEnv* env, jobject thiz )
{
   int Value = env->GetIntField(thiz, gNativeObjectHolderFieldID);
   iVehicle* Obj = (iVehicle*)Obj;

   // todo: add checks here, for NULL and for dynamic casting

   Obj->Run();
}

类似的代码用于GetSize().

然后创建一个 Java 实例,Bot您必须调用CreateNativeObject()并将返回的值分配给该NativeObjectHolder字段。

JNIEXPORT int JNICALL Java_com_test_iVehicle_CreateNativeObject( JNIEnv* env, jobject thiz )
{
   iVehicle* Obj = new iVehicle;
   return (int)Obj;    
}

所以,这就是方案。要完成这项工作,您需要添加破坏代码并解析 C++ 类以生成所有这些胶水代码。

添加:

如果 whereiVehicle实际上是抽象的,则必须生成一个可以实例化的非抽象包装器:

class iVehicle
{
   virtual void Run() = 0;
}

class iVehicle_Wrapper: public iVehicle
{
   virtual void Run() { ERROR("Abstract method called"); };
}

iVehicle_WrapperCreateNativeObject(). 瓦拉!您在 Java 中继承了一个抽象 C++ 类。

于 2013-08-07T20:29:40.273 回答