swig扩展一个带有变量的模板类 [英] swig extending a templated class with variable

查看:170
本文介绍了swig扩展一个带有变量的模板类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立一个Swig接口到模板类。在我的pyinterface.i文件中,我声明

I am building a Swig interface to a templated class. In my pyinterface.i file, I declare

%template (myclass) MyClass<int>;



现在我想做的是在我的新类中添加一个字段变量,以

Now what I want to do, is add a field variable to my new class, which I assume should be done as

%extend MyClass<int>{
    double x;
}

但是,抱怨没有


myclass_get_x

myclass_get_x

所以如果我尝试通过修改上面的来定义这个:

method defined. So if I try to define this by modifying the above to:

%extend MyClass<int>{
    double x;
    double MyClass<int>_get_x(MyClass<int> *f){
            return (*f)->x;
    }
}

然后我得到语法错误。

我试过这样做:

%extend myclass{
    double x;
    double myclass_get_x(myclass *f){
            return (*f)->x;
    }
}

但这也会抛出错误,因为myclass不

But this also throws errors, as myclass doesn't seem to be understood yet.

推荐答案

扩展%extend 你不能真正添加​​任何新的成员变量,只有成员函数。如果你在%extend 中这样做,就会假定存在get / set函数。

When you extend a class with %extend you can't really add any new member variables, only member functions. It will assume the existence of a get/set function if you do this in %extend.

这就是为新的成员变量的存储(即内存)将不得不住在某个地方,但没有明显的安全地方放置它。你不能修改原来的C ++ class ,因为如果你这样做,最终会出现未定义的行为,当一些其他的预编译代码使用类的旧定义;没有办法回顾性地应用新的定义。您不能将其放在以目标语言生成的代理中,因为在目标语言中C ++类和代理之间没有1:1映射。 (考虑两个函数,它们都通过一个指针返回相同的全局实例,以了解这可能发生的一个简单例子)。

The reason for this is that the storage (i.e. memory) for the new member variables would have to live somewhere, but there's no obvious safe place to put it. You can't modify the original C++ class, because if you do you'll end up with undefined behaviour when some other, pre-compiled code uses the old definition of the class; there's no way to retrospectively apply the new definition. You can't put it in the proxy that gets generated in the target language, because there isn't a 1:1 mapping between instances of C++ classes and proxies in the target language. (Consider two functions that both return the same global instance via a pointer for the trivial example of how this may occur).

如果你想实现get / set函数做一些有用的事情(例如,这里我使用一个全局地图存储额外的数据)你不想实现它们%extend 例如,给test.hh只是:

If you wanted to implement the get/set functions to do something useful (e.g. here I used a global map to store the extra data) you don't want to implement them inside %extend For example, given test.hh with just:

template <typename T>
struct Foo {};

您可以使用 std :: map 通过在包装器中编写自己的get和set作为自由函数来做你想做的事情 - %{%} 只是直接传递代码:

You can use a std::map to do what you're trying to do by writing your own gets and sets as free functions in the wrapper - %{ %} just passes the code straight through:

%module test

%include "test.hh"

%{
#include "test.hh"
%}

%{
#include <map>
static std::map<Foo<int>*, double> extra_stuff;

const double& Foo_Sl_int_Sg__x_get(Foo<int>* f) {
  return extra_stuff[f];
}

void Foo_Sl_int_Sg__x_set(Foo<int>* f, const double& d) {
  extra_stuff[f] = d;
}
%}

%template(FooInt) Foo<int>;

%extend Foo<int> {
  double x;
}

get / set函数由SWIG自己的管理系统修改,因为它是一个模板。我只是看看生成的包装类看看他们被称为。 (我认为可能有一个更聪明的方式来做,但我不能从文档中找出它)。如果它不是一个模板的名称的功能将是更简单。

The get/set functions are mangled by SWIG's own mangling system because it's a template. I just looked in the generated wrapper class to see what they were called. (I think there might be a smarter way to do that but I couldn't figure it out from the documentation yet). If it wasn't a template the name of the functions would be much simpler.

请注意,这里没有规定从这个地图中删除条目 - 它会成长无限期。 (你可以解决这个问题,例如通过提供在对象生命结束时调用额外函数的typemap)。你还需要注意线程。

Note that there's no provision here for ever removing entries from this map - it will just grow indefinitely. (You can work around that for example by providing a typemap that calls an extra function at the end of an Object's life). You also need to be careful about threads.

因为你没有指定你使用什么语言,我用Java测试了上面的代码:

Since you didn't specify what language you were using I tested the above code with Java:

public class run {
  public static void main(String[] argv) {
    System.loadLibrary("test");
    FooInt f = new FooInt();
    f.setX(0.1);
    System.out.println(f.getX());
  }
}

或者如果你真的想写代码确保目标语言中有唯一的单个代理实例,通过编写一个typemap来检查是否已经创建了一个代理,而不是总是创建一个代理,但是引发了引用计数和线程安全的问题,这些问题很难有效地解决,

Alternatively if you really want to you can write code to ensure that there is a unique single proxy instance in the the target language, by writing a typemap that checks if an proxy has been created instead of always creating one, but that raises issues with reference counting and thread safety that are hard to address efficiently and generically, which is why it's not the default behaviour.

很多情况下最简单的解决方法(例如目标语言的迭代器)虽然是使用%inline 来声明和定义一个全新的额外类,并提供您想要的功能。

The simplest workaround in a lot of cases (e.g. iterators in the target language) though is to use %inline to declare and define and wrap all at once an entirely new extra class that that provides the functionality you want.

这篇关于swig扩展一个带有变量的模板类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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