好的,有一个关键字我有意远离标签和标题。这就是“Android”,但那是因为即使该项目在Android中,我认为我的问题与它没有任何关系,并且我不想吓唬没有Android经验的人。SWIG Java保留从C++弹起的对象的类信息
所以,通常与swig相关的问题。我在C++类中有一个虚拟方法,我通过在类中添加director
功能使它在Java中可以重载,并且工作正常。问题是该方法接收到一个多态的参数,这个参数在java端也被扩展了,并且在Java中的虚拟方法调用期间,该对象带有全部的多态信息。
为了呈现确切的情况;我正在用C++编写游戏引擎,并且我想在Java中愉快地使用它。游戏引擎有一个GameObject
类,其中注册了CollisionListener
,并且当碰撞引擎检测到碰撞事件时,它调用所有注册的的collidedWith(GameObject & collidee)
方法将它们与他们碰撞的对象进行传递。
class CollisionListener {
public:
virtual bool collidedWith(GameObject &){};
~CollisionListener(){} // I know this needs to be virtual but let's forget about that now
};
我用下面的接口文件Bridge.i
%module(directors="1") Bridge
%feature("director") CollisionListener;
%include "CollisionListener";
%feature("director") GameObject;
%include "GameObject.h"
现在揭露这个类,与GameObject
类一起去渣,当我在Java和超载collidedWith
从CollisionListener
继承,它得到的所谓用java端GameObject
对象。例如,如果我继承了java类GameObject
类并定义了Bullet
类,那么当此子弹与另一个具有侦听器的对象发生冲突时,在collidedWith
方法调用中,我收到的所有内容都是空的GameObject
,因此(object instanceof Bullet)
不起作用。毫不奇怪,我已经挖成痛饮产生BridgeJNI.java
,发现这个:
public static boolean SwigDirector_CollisionListener_collidedWith(CollisionListener self, long arg0) {
return self.collidedWith(new GameObject(arg0, false));
}
所以它包装围绕指针的新对象调用Java过载前。
所以,主要问题是如何在发生碰撞时收到Bullet
对象?
我想出了一种方法来轻松实现,但我需要修改自动生成的文件,这是一个坏主意。所以我希望一些swig master可以帮我将修改注入swig生成的文件。
我的小黑客就是保持jobject * self
在每一个C++侧GameObject
对象,而真正的Java端GameObject
(而不是说只是包装指针之一)施工过程中指定真正的Java对象的地址。这样,我可以在C++端GameObject
中定义一个多态的getSelf
方法,并在java中愉快地使用结果。有没有办法将必要的代码注入swig生成的文件?
感谢
注意:如果你试图在Android董事,他们都没有奏效,这是因为当前稳定版本不支持它。从swig网站下载Bleeding Edge。但是我在2012年3月22日写这篇文章,这个说明很快就没有必要了。析构函数不是虚拟的原因在于Bleeding Edge版本使得程序在析构函数中崩溃,并且使其非虚拟化现在似乎可以控制它。
所以你的问题的简短版本是你想能够(例如)在Java中派生'GameObject'并且仍然能够在Java派生类型被传递给'collidedWith'的Java实现时在Java中进行投射?很确定你的小黑客可以包装在类型图中,如果是这样的话。 – Flexo 2012-03-23 18:22:31
准确!我认为swig会有注入代码的方式,但我对swig很陌生。我会检查typemaps。 – enobayram 2012-03-23 18:47:22
那么我会在明天写一个答案。 – Flexo 2012-03-23 18:50:49