swig c ++ w / Java在多态回调函数上丢失类型

可能重复:
SWIG Java保留从C ++反弹的对象的类信息

问题 :为什么我的C ++ swigged对象在传递给Java回调函数时会丢失其类型?

安装程序 :我已经使用Swig Java示例进行回调并添加了一个要传递给回调run(Parent p)的对象run(Parent p) 。 回调按预期工作,但是当我传递一个Child对象时,Java似乎失去了它的类型,并认为它的类型为Parent ,它应该是Child 。 这基于Swig java回调示例 。

系统信息 :Ubuntu 8.04 w / Swig 1.3.33 – 关于最新Swig产生差异的机会我也测试了1.3.39 – 这没有效果。

产出

 bash $ java -Djava.library.path =。 邵仁枚
添加并调用普通的C ++回调
 ----------------------------------------
回调::运行(5Child)
回调::〜回调()

添加和调用Java回调
 ------------------------------------
 JavaCallback.run(家长)
回调::运行(5Child)
回调::〜回调()

正如你在输出中看到的那样 – 对象实际上是Child类型 – 但它的Java类名是Parent – 这是错误的……

如果你查看Java回调run(Parent p)你可以看到我在哪里获取Java类,而Java确实认为这个对象是Parent类型 – 试图将它转换为Child将按预期抛出ClassCastException

代码

 /* File : example.i */ %module(directors="1") example %{ #include "example.h" %} %include "std_string.i" /* turn on director wrapping Callback */ %feature("director") Callback; %include "example.h" /* File : example.h */ #include  #include  #include  #include  class Parent { public: virtual const char* getName() { return typeid(*this).name(); } }; class Child : virtual public Parent { }; class Callback { public: virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; } virtual void run(Parent& p) { std::cout << "Callback::run(" << p.getName() << ")" <run(*p); delete p; } }; /* File: runme.java */ public class runme { static { try { System.loadLibrary("example"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); System.exit(1); } } public static void main(String[] args) { System.out.println("Adding and calling a normal C++ callback"); System.out.println("----------------------------------------"); Caller caller = new Caller(); Callback callback = new Callback(); caller.setCallback(callback); caller.call(); caller.delCallback(); callback = new JavaCallback(); System.out.println(); System.out.println("Adding and calling a Java callback"); System.out.println("------------------------------------"); caller.setCallback(callback); caller.call(); caller.delCallback(); // Test that a double delete does not occur as the object has already been deleted from the C++ layer. // Note that the garbage collector can also call the delete() method via the finalizer (callback.finalize()) // at any point after here. callback.delete(); System.out.println(); System.out.println("java exit"); } } class JavaCallback extends Callback { public JavaCallback() { super(); } public void run(Parent p) { System.out.println("JavaCallback.run("+p.getClass().getSimpleName()+")"); super.run(p); } } # File: Makefile TOP = ../.. SWIG = $(TOP)/../preinst-swig CXXSRCS = example.cxx TARGET = example INTERFACE = example.i SWIGOPT = all:: java java:: $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' java_cpp javac *.java clean:: $(MAKE) -f $(TOP)/Makefile java_clean check: all 

这可能是Swig中的一个错误 – 但我希望这是我对C ++类型/转换的愚蠢行为……

任何想法将不胜感激!

在周末探讨了这个问题后,我想这是Swig在C ++类和Java之间存在的“常见”问题。 该问题被称为向下转型 ,是董事的常见问题。 不幸的是,导演似乎无法处理这个简单的案例。 我尝试了导演的每一个组合 – 如下所示

 %feature("director") Callback; %feature("director") Parent; %feature("director") Child; 

这些似乎都没有任何帮助,但做下面的黑客工作正常:

 class Callback { public: virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; } virtual void run(Parent& p) { std::cout << "Callback::run1(" << p.getName() << ")\n"; } virtual void run(Child& c) { std::cout << "Callback::run2(" << c.getName() << ")\n"; } }; 

然后在java类中,无论你需要什么子类型,都需要重载irons。

 class JavaCallback extends Callback { public void run(Child p) { out.p("JavaCallback.run("+p.getClass().getSimpleName()+")"); out.p("p.getName() = "+p.getName()); super.run(p); } } 

然后神奇地输出工作

 bash $ java -Djava.library.path =。 邵仁枚
添加并调用普通的C ++回调
 ----------------------------------------
做孩子
子类型父类
回调:: RUN2(5Child)
回调::〜回调()
添加和调用Java回调
 ------------------------------------
 JavaCallback.run(儿童)
 p.getName()= 5Child
回调:: RUN2(5Child)
回调::〜回调()
 java退出

应该有一个更好的方法来做到这一点,但没有一个Swig文档向我提供了一个如何正确执行此操作的明确示例。 在libsbml库中有一些非常令人印象深刻的代码可能会帮助人们创建解决问题的向下转换类型图,但这对于少量输出来说certificate非常复杂......无论如何这简单易行。

如果有人能够找到一个简单的(人类)解决方案,我会有兴趣听到它。

我今天遇到了一篇博客文章,它专门讨论了SWIG,C ++,C#中的向下转型类型 - 无论如何,它可能是一个很好的方向。