假设我们有一个 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++ 没有为反射提供好的内置功能。iVehicle
super
iVehicle::GetSize()
Bot
iVehicle*
这是一种可能的解决方案。
要在 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_Wrapper
在CreateNativeObject()
. 瓦拉!您在 Java 中继承了一个抽象 C++ 类。