使用 JNI 子类化 Java 中的 C++ 抽象类 [英] Subclass a C++ abstract class in Java using JNI
问题描述
我有一个必须在现有 Android 实现中使用的 C++ 库.我正在使用 Android NDK 并通过 JNI 使用 C++ 类.
I have a C++ library that I have to use in an existing Android implementation. I'm using Android NDK and using the C++ classes via JNI.
但是,我无法找到如何使用 JNI 在 Java 中对 C++ 抽象类进行子类化.
However, I am not able to find how to subclass a C++ abstract class in Java using JNI.
我面临的问题:我的目标是通过继承抽象 C++ 类为 C++ 中的虚拟方法提供 Java 实现.我已经加载了本机库,并且正在尝试声明本机方法.C++ 方法有关键字'virtual'.当我在加载 C++ 库后在 Java 中声明本机函数时,无法识别虚拟".这里有什么问题?
Problems I face: My aim is to provide Java implementation for the virtual methods in C++ by subclassing the abstract C++ class. I have loaded the native library and I'm trying to declare the native methods. The C++ methods have keyword 'virtual'. When I declare the native functions in Java after loading the C++ library, 'virtual' is not recognized. What is wrong here?
感谢任何帮助.我是 JNI 的新手.提前致谢.
Any help is appreciated. I'm a newbie to JNI. Thanks in advance.
推荐答案
假设我们有一个 C++ 类:
Let's consider we have a C++ class:
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 中创建一个类 Bot
来扩展类 iVehicle
,即调用 super
调用来自 iVehicle::GetSize()
并且从 C++ 的角度来看,我们可以将 Bot
的实例用作 iVehicle*
变量.这很难,因为 C++ 没有为反射提供好的内置功能.
We want to create a class Bot
in Java that extends class iVehicle
in the sense that calls to super
invoke the C++ code from iVehicle::GetSize()
and, from the C++ point of view, we can use the instances of Bot
as iVehicle*
variables. That's tough since C++ provides no good built-in functionality for reflection.
这是一种可能的解决方案.
要在 Java 中使用 C++ 类,我们需要生成一个 Java 包装器,即:
To use C++ class in Java we need to generate a Java wrapper, i.e:
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中的用法很简单:
The usage in Java is simple:
class Bot extends iVehicle
{
public int GetSize()
{
if ( condition ) return 0;
// call C++ code
return super.GetSize();
}
}
但是,这段代码有一个 C++ 部分:
However, there is a C++ part to this code:
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
字段.
Then creating an instance of Java's Bot
you have to call CreateNativeObject()
and assign the returned value to the NativeObjectHolder
field.
JNIEXPORT int JNICALL Java_com_test_iVehicle_CreateNativeObject( JNIEnv* env, jobject thiz )
{
iVehicle* Obj = new iVehicle;
return (int)Obj;
}
所以,这就是方案.要完成这项工作,您需要添加销毁代码并解析 C++ 类以生成所有这些胶水代码.
So, this is the scheme. To make this work you will need to add the destruction code and to parse C++ classes to generate all this glue code.
添加:
如果 iVehicle
实际上是抽象的,您将必须生成一个可以实例化的非抽象包装器:
In case where iVehicle
is actually abstract you will have to generate a non-abstract wrapper that you are able to instantiate:
class iVehicle
{
virtual void Run() = 0;
}
class iVehicle_Wrapper: public iVehicle
{
virtual void Run() { ERROR("Abstract method called"); };
}
并在CreateNativeObject()
中实例化iVehicle_Wrapper
.瓦拉!您在 Java 中继承了一个抽象 C++ 类.
And instantiate iVehicle_Wrapper
in CreateNativeObject()
. Vuala! You have inherited an abstract C++ class in Java.
这篇关于使用 JNI 子类化 Java 中的 C++ 抽象类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!