使用JNI子类化Java中的C ++抽象类 [英] Subclass a C++ abstract class in Java using JNI

查看:177
本文介绍了使用JNI子类化Java中的C ++抽象类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆