我已经解决了这个问题。但是,这并不是您在问题中建议的解决方案,它在Java方面有更多代码,在JNI / C
++方面没有更多的代码。(我发现这样做的方法很棘手,要想在所有可能的情况下正确无误)。
我将类简化为单个头文件:
class GameObject {};class CollisionListener {public: virtual bool collidedWith(GameObject &) { return false; } virtual ~CollisionListener() {} };inline void makeCall(GameObject& o, CollisionListener& c) { c.collidedWith(o);}
这
makeCall实际上使问题变得显而易见。
我使用的技巧是注册所有Java衍生的实例
GameObject中
HashMap自动创建时。然后,在调度Director调用时,这只是在HashMap中查找它的问题。
然后是模块文件:
%module(directors="1") Test%{#include "test.hh"%}%pragma(java) jniclasspre=%{ static { try { System.loadLibrary("test"); } catch (UnsatisfiedlinkError e) { System.err.println("Native pre library failed to load. n" + e); System.exit(1); } }%}// An import for the hashmap type%typemap(javaimports) GameObject %{import java.util.HashMap;import java.lang.ref.WeakReference;%}// Provide a static hashmap, // replace the constructor to add to it for derived Java types%typemap(javabody) GameObject %{ private static HashMap<Long, WeakReference<$javaclassname>> instances = new HashMap<Long, WeakReference<$javaclassname>>(); private long swigCPtr; protected boolean swigCMemOwn; public $javaclassname(long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; // If derived add it. if (getClass() != $javaclassname.class) { instances.put(swigCPtr, new WeakReference<$javaclassname>(this)); } } // Just the default one public static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } // Helper function that looks up given a pointer and // either creates or returns it static $javaclassname createOrLookup(long arg) { if (instances.containsKey(arg)) { return instances.get(arg).get(); } return new $javaclassname(arg,false); }%}// Remove from the map when we release the C++ memory%typemap(javadestruct, methodname="delete", methodmodifiers="public synchronized") GameObject { if (swigCPtr != 0) { // Unregister instance instances.remove(swigCPtr); if (swigCMemOwn) { swigCMemOwn = false; $imclassname.delete_GameObject(swigCPtr); } swigCPtr = 0; }}// Tell SWIG to use the createOrLookup function in director calls.%typemap(javadirectorin) GameObject& %{ $javaclassname.createOrLookup($jniinput)%}%feature("director") GameObject;// Finally enable director for CollisionListener and include the header%feature("director") CollisionListener; %include "test.hh"
请注意,由于所有Java实例都存储在中,因此
HashMap我们需要使用a
WeakReference来确保我们不会延长其寿命并防止发生垃圾收集。如果您在乎线程,则在适当时添加同步。
我用以下方法对此进行了测试:
public class main { public static void main(String[] argv) { JCollisionListener c = new JCollisionListener(); JGameObject o = new JGameObject(); c.collidedWith(o); Test.makeCall(o,c); }}
哪里
JCollisionListener是:
public class JCollisionListener extends CollisionListener { public boolean collidedWith(GameObject i) { System.out.println("In collide"); if (i instanceof JGameObject) { System.out.println("Is J"); } else { System.out.println("Not j"); } JGameObject o = (JGameObject)i; return false; }}
并且
JGameObject是:
public class JGameObject extends GameObject {}
(作为参考,如果您想使用其他方法,您将在编写类型
directorin映射时进行查看)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)