vpl*_*lus 5 java-native-interface android-ndk
我有一个C++库,我必须在现有的Android实现中使用它.我正在使用Android NDK并通过JNI使用C++类.
但是,我无法找到如何使用JNI在Java中子类化C++抽象类.
我面临的问题:我的目标是通过继承抽象C++类为C++中的虚方法提供Java实现.我已经加载了本机库,我正在尝试声明本机方法.C++方法有关键字'virtual'.当我在加载C++库后在Java中声明本机函数时,无法识别"virtual".这有什么不对?
任何帮助表示赞赏.我是JNI的新手.提前致谢.
让我们考虑一下我们有一个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
};
Run Code Online (Sandbox Code Playgroud)
我们希望Bot在Java中创建一个类,它iVehicle在super调用C++代码的意义上扩展了类iVehicle::GetSize(),从C++的角度来看,我们可以使用Botas iVehicle*变量的实例.这很难,因为C++没有为反射提供良好的内置功能.
这是一种可能的解决方案.
要在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();
}
Run Code Online (Sandbox Code Playgroud)
Java中的用法很简单:
class Bot extends iVehicle
{
public int GetSize()
{
if ( condition ) return 0;
// call C++ code
return super.GetSize();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这段代码有一个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();
}
Run Code Online (Sandbox Code Playgroud)
类似的代码是为了GetSize().
然后创建Java的实例,Bot您必须调用CreateNativeObject()并将返回的值分配给该NativeObjectHolder字段.
JNIEXPORT int JNICALL Java_com_test_iVehicle_CreateNativeObject( JNIEnv* env, jobject thiz )
{
iVehicle* Obj = new iVehicle;
return (int)Obj;
}
Run Code Online (Sandbox Code Playgroud)
所以,这就是计划.要完成这项工作,您需要添加销毁代码并解析C++类以生成所有这些粘合代码.
添加:
如果iVehicle实际上是抽象的,则必须生成一个可以实例化的非抽象包装器:
class iVehicle
{
virtual void Run() = 0;
}
class iVehicle_Wrapper: public iVehicle
{
virtual void Run() { ERROR("Abstract method called"); };
}
Run Code Online (Sandbox Code Playgroud)
并实例iVehicle_Wrapper在CreateNativeObject().Vuala!您已经在Java中继承了一个抽象的C++类.