将 shared_ptr 与 SWIG Director for Java 结合使用 [英] Using shared_ptr with SWIG Directors for Java

查看:29
本文介绍了将 shared_ptr 与 SWIG Director for Java 结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始掌握 SWIG 的窍门,并且 SWIG 的最新版本 (v3.0) 似乎可以处理我需要的所有开箱即用的功能,包括 C++11 功能,但我遇到了在我的导演类中使用 shared_ptr 时遇到了障碍.

I'm starting to get the hang of SWIG, and the latest version(v3.0) of SWIG seems to handle just about everything I need out of the box, including C++11 features, but I have hit a snag when it comes to using shared_ptr with my director classes.

我已经能够让 shared_ptr 很好地与普通代理类一起工作,但现在在我的导演上,它似乎不受开箱即用的支持.它给了我自动生成的类型,比如 SWIGTYPE_p_std__shared_ptrT_MyDataType_t 并且正在生成一个损坏的接口,因为它使用的类型与代理类使用的类型不同.

I have been able to get shared_ptr to work with normal proxy classes great, but now on my directors, it seems to not be supported out of the box. It is giving me the auto-generated type like SWIGTYPE_p_std__shared_ptrT_MyDataType_t and is generating a broken interface because it isn't using the same types that the proxy classes use.

我有一个我正在尝试做的简化示例(在 swig 3.0 上使用 swig -c++ -java Test.i 运行):

I have a simplified example of what I'm trying to do (run with swig -c++ -java Test.i on swig 3.0):

Test.i

%module(directors="1") test
%{

%}

%include <std_shared_ptr.i>

%shared_ptr(MyDataType)

class MyDataType {
public:
    int value;
};

class NonDirectorClass {
public:
    std::shared_ptr<MyDataType> TestMethod();
};

%feature("director") CallbackBaseClass;

class CallbackBaseClass {
public:
    virtual ~CallbackBaseClass() {};
    virtual std::shared_ptr<MyDataType> GetDataFromJava() {};
};

基本上我要做的是在 Java 中扩展 CallbackBaseClass 并且我希望能够传递我的 shared_ptr 包装类型.非导演类生成 shared_ptr 类型就好了.导演类代理文件正确生成,但包装器中的 SwigDirector_ 方法引用了不正确的类型.

Basically what I'm going to be doing is extending the CallbackBaseClass in Java and I want to be able to pass around my shared_ptr wrapped types. The non-director class generates the shared_ptr types just fine. The director class proxy files get generated correctly, but the SwigDirector_ methods in the wrapper reference the incorrect types.

似乎我可以通过在任何地方将 SWIGTYPE_p_std__shared_ptrT_MyDataType_t 的类型更改为 MyDataType 来手动修复文件,但我希望有更多 swig 知识的人可以回答这个问题所以这可以正确生成.

It seems like I could manually repair the files by changing the type of SWIGTYPE_p_std__shared_ptrT_MyDataType_t to MyDataType everywhere, but I'm hoping someone with more swig knowledge can answer the question so this can be generated correctly.

我拥有的最好线索是这里,但我仍在努力弄清楚如何正确使用这些类型映射,尤其是对于 shared_ptr 而不是基本原语.

The best clue I have is here, but I'm still trying to figure out how to correctly use these type maps, especially for shared_ptr and not basic primitives.

更新:

文档:

注意:目前不支持 %shared_ptr 和 Director 功能.

Note: There is currently no support for %shared_ptr and the director feature.

虽然它没有说明原因.我想知道这对于 swig 导演是否不可能,如果有充分的理由为什么不在导演中使用 shared_ptr.使用您在其他任何地方使用的相同类型似乎是有意义的.我希望答案仍然是可能的.

Though it gives no indication as to why. I'd like to know if this is an impossibility with swig directors, if there is a good reason why not to use shared_ptr in directors. It seems like it makes sense to use the same types you use everywhere else. I hope the answer is it is still possible.

推荐答案

SWIG 文档的最新版本现为:

The latest version of the SWIG documentation now reads:

%shared_ptr 的支持有些有限,而且导演功能和成功程度因不同的目标语言而异.请通过提供改进的补丁来帮助改进这种支持.

"There is somewhat limited support for %shared_ptr and the director feature and the degress of success varies among the different target languages. Please help to improve this support by providing patches with improvements."

为了使您的示例工作,我们似乎需要添加四个缺失的类型映射,directorin、directorout、javadirectorin 和 javadirectorout:

To make your example work we seem to need to add four missing typemaps, directorin, directorout, javadirectorin and javadirectorout:

%module(directors="1") test

%include <std_shared_ptr.i>

%{
#include <memory>
#include <iostream>
%}

%shared_ptr(MyDataType)

%feature("director") CallbackBaseClass;

%typemap(javadirectorin) std::shared_ptr<MyDataType> "new $typemap(jstype, MyDataType)($1,true)";
%typemap(directorin,descriptor="L$typemap(jstype, MyDataType);") std::shared_ptr<MyDataType> %{
  *($&1_type*)&j$1 = new $1_type($1);
%}

%typemap(javadirectorout) std::shared_ptr<MyDataType> "$typemap(jstype, MyDataType).getCPtr($javacall)";
%typemap(directorout) std::shared_ptr<MyDataType> %{
  $&1_type tmp = NULL;
  *($&1_type*)&tmp = *($&1_type*)&$input;
  if (!tmp) {
    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
    return NULL;
  }
  $result = *tmp;
%}

%inline %{
class MyDataType {
public:
    int value;
};

class NonDirectorClass {
public:
    std::shared_ptr<MyDataType> TestMethod() { return std::make_shared<MyDataType>(); }
};

class CallbackBaseClass {
public:
    virtual ~CallbackBaseClass() {};
    virtual std::shared_ptr<MyDataType> GetDataFromJava() = 0;
};

void frobinate(CallbackBaseClass& cb) {
    std::cout << "In C++: " << cb.GetDataFromJava()->value << "\n";
}
%}

即使您只在示例中使用过directorout 情况,仍然需要directorin 类型映射才能使director_connect 中的查找成功,因为这取决于拥有正确的描述符.

Even though you only ever use the directorout case in your sample the directorin typemap is still required to make the lookup in director_connect succeed, because it depends upon having the correct descriptor.

这四种类型映射在功能上与 in、javain 和 javaout 类型映射等效,但由于它们在董事中的角色而颠倒过来.

These four typemaps are equivilent to the in, javain and javaout typemaps in functionality, but reversed because of their role in directors.

它们不够完整,无法处理所有情况,但它们适用于您的示例.描述符中的 $typemap 调用需要一个比 Ubuntu 14.04 中包含的版本更新的 SWIG 3 版本 - 在我编写它的形式中,我测试的唯一版本是从主干中检出的.您可以手动编写描述符(它只是 descriptor="LMyDataType;"),但显然这不太通用.如上所述编写它的优点是它也可以正确处理 %rename 指令.但这也不能正确处理包,因此在这种情况下您也必须再次手动编写它.

They're not complete enough to handle all cases, but they work in your example. The $typemap call inside the descriptor needs a version of SWIG 3 newer than the one included in Ubuntu 14.04 - in the form I wrote it the only version I tested with was checked out from the trunk. You can write the descriptor by hand (which would just be descriptor="LMyDataType;"), but clearly that's less generic. The advantage of writing it as above is that it will handle %rename directives correctly too. This won't handle packages properly though either so you would have to write it manually again in that case too.

我能够测试并运行该示例,我添加了以下 run.java:

I was able to test and run the example, I added the following run.java:

public class run extends CallbackBaseClass {
  public MyDataType GetDataFromJava() {
    MyDataType val = new MyDataType();
    val.setValue(123);
    return val;
  }

  public static void main(String[] argv) {
    System.loadLibrary("test");
    run r = new run();

    System.out.println("In Java: " + r.GetDataFromJava().getValue());
    test.frobinate(r);
  }
}

并编译并运行它:

~/swig-trunk/preinst-swig -Wall -c++ -java  test.i  
clang++-3.6 -stdlib=libc++ -Wall -Wextra -std=c++1y test_wrap.cxx -o libtest.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux -shared -fPIC 
javac run.java
LD_LIBRARY_PATH=. java run

运行时给出:

In Java: 123
In C++: 123

我猜想,对于带有 shared_ptr+directors 的 Java 来说,正确使用描述符的微妙之处可能是阻止这种正常工作"开箱即用的主要障碍.

I would guess that in the case of Java with shared_ptr+directors the subtleties around getting the descriptor right are probably the main blocker to having this "just work" out the box.

这篇关于将 shared_ptr 与 SWIG Director for Java 结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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