使用JNI子类化Java中的C ++抽象类 [英] Subclass a C++ abstract class in Java using JNI
问题描述
我有一个C ++库,必须在现有的Android实现中使用.我正在使用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中创建一个扩展类iVehicle
的类Bot
,即对super
的调用从iVehicle::GetSize()
调用C ++代码,从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屋!