我使用SWIG类型映射包装一个类,使用SWIG提供的“std_vector.I”包装这个类的std::vector
。目标语言是Python。除了我不能在向量上迭代之外,一切似乎都正常。
我创建了一个关于复数的最小示例(仅为方便起见,它与我的真实项目无关)。
这是我想包装的C类:
struct Komplex
{
Komplex() : real(0.0), imag(0.0) {}
double real;
double imag;
};
这是我的SWIG接口文件:
%module myproject
%{
#include "komplex.h"
%}
%typemap(typecheck) Komplex&
{
PyComplex_Check($input) ? 1 : 0;
}
%typemap(in) Komplex& (Komplex temp)
{
temp.real = PyComplex_RealAsDouble($input);
temp.imag = PyComplex_ImagAsDouble($input);
$1 = &temp;
}
%typemap(out) Komplex&
{
$result = PyComplex_FromDoubles($1->real, $1->imag);
}
// define a vector of the wrapped class:
%include "std_vector.i"
%template(KomplexVector) std::vector<Komplex>;
我可以使用以下Python代码简单地测试typecheck/in/out typemaps:
import myproject
# fill a vector (the "typecheck" and "in" typemaps are used!)
vec = myproject.KomplexVector()
vec.append( complex(1,2) )
# below, the output typemap is used:
print("First attempt:")
for i in xrange(len(vec)):
print(vec[i]) # prints: (1+2j)
assert vec[i] == complex(1,2) # OK
# below, the output typemap is NOT used:
print("Second attempt:")
for k in vec:
print(k) # prints: <Swig Object of type 'Komplex *' at 0x7f0194c6de10>
assert k == complex(1,2) # fails!
正如您在输出中看到的,在向量上迭代会产生不透明的值:
First attempt:
(1+2j)
Second attempt:
<Swig Object of type 'Komplex *' at 0x7f0194c6de10>
Traceback (most recent call last):
File "test.py", line 17, in <module>
assert k == complex(1,2) # fails!
AssertionError
swig/python detected a memory leak of type 'Komplex *', no destructor found.
所以我的问题很简单:我怎样才能让它工作?
我尝试了以下方法:
Komplex
值/指针/引用/const引用/...std::向量定义in/out/varout/... typemaps
...都无济于事。
完整的源代码(包括Linux/g的一个小构建脚本)可以在这里找到。
感谢任何帮助!
编辑:有一些变通方法可以避免缺少正确包装的迭代器,但它们都不漂亮(我认为)。例如,一种可能性是在Python中定义一个自定义迭代器对象,并让SWIG修改Python代码中的
迭代器
和插入
方法。
例如,以下代码将确保向量中k的
:
和
vec。插入(1,复杂(4,5))
将产生预期的行为:
%pythoncode %{
class MyVectorIterator(object):
def __init__(self, pointerToVector):
self.pointerToVector = pointerToVector
self.index = -1
def next(self):
self.index += 1
if self.index < len(self.pointerToVector):
return self.pointerToVector[self.index]
else:
raise StopIteration
%}
%rename(__cpp_iterator) std::vector<Komplex>::iterator;
%rename(__cpp_insert) std::vector<Komplex>::insert;
%extend std::vector<Komplex> {
%pythoncode {
def iterator(self):
return MyVectorIterator(self)
def insert(self, i, x):
if isinstance(i, int): # "insert" is used as if the vector is a Python list
_myproject.KomplexVector___cpp_insert(self, self.begin() + i, x)
else: # "insert" is used as if the vector is a native C++ container
return _myproject.KomplexVector___cpp_insert(self, i, x)
}
}
%include "std_vector.i"
%template(KomplexVector) std::vector<Komplex>;
我不会称之为“解决方案”(更不用说“好”的解决方案),但我想它可以作为一种临时解决方案...
我可以通过添加以下行(我在share/swig/python/pyiterators.swg中找到了这个符号)来摆脱STL容器自动生成的包装中的_____
函数。我归档
#define SWIGPYTHON_BUILTIN
在此之后,将生成。py
文件不再包含____
例程,因此Python退回到使用___
的方式,如上面其他答案所述。我不知道为什么会这样。(SWIG只是一种尝试
但这可能是一个相当大的黑客,因为我假设这个定义通常只在使用SWIG标志-builtin
时设置。但我没有这样做,我只是添加了定义。所以这可能会导致未定义的行为。然而,对我来说,它目前为止还有效...
现在有点晚了,但让我记录一下我在这里发现的类似问题的解决方案:如果在包含任何SWIG头之前简单地定义SWIG\u NO\u EXPORT\u迭代器\u方法,事情似乎都很好。这是一个相当直截了当的工具,因为它完全禁用了迭代器支持,正如它所说的。对于向量,它仍然允许工作,并以最佳方式工作。然而,当Python退回到在循环中调用
\uuuu getitem\uuu
时,如果对象没有实现\uu iter\uuu
,它就会失败,这正是向量迭代的工作方式。
请注意,SWIG还为其他容器类型生成
\uuuu getitem\uuuuu
,例如std::list
和std::set
,但它的实现对它们来说当然是低效的,因此如果使用这些容器,这种解决方法并非没有成本。
我在目标语言为python的swig接口文件中成功地使用了以下类型映射: 然而,当我将目标语言更改为java时,当我尝试构建swg生成的自动生成的c包装代码时,我会遇到很多编译时错误,即。 等等... 我注意到,在python案例中,粘贴到swig包装器代码中的代码包含,等声明,这些代码来自 它位于 当目标语言为java时,此等效代码不会粘贴到swig包装器代码中。我不完全确定为什么不会发生这种情
如何将此迭代器与泛型类型一起使用?以下是我在“main”函数中尝试的方法: 结果是:<代码>无法从静态上下文引用非静态类项 结果是:<代码>无法从静态上下文引用非静态类项 结果: 编辑: 我调用的是类而不是方法。这项工作: 迭代器it=deq。迭代器(); 我认为,由于iterator()中返回的实例的类型是ListIterator,因此我需要使用该类型声明“it”。
我试图使用一个自定义类作为的键,如下所示: 但是,g给出了以下错误: 我想,我需要告诉C如何散列类,然而,我不太确定如何做。我怎样才能完成这些任务?
我有两个对象,除了date成员外,其他成员都相同。在obj1中,date是java.sql.date,obj2.date是long(纪元)。 我需要编写一个映射器来将obj1映射到obj2。这就是我试图做的: 但是mapperImpl只有自己的日期转换实现: 我得到了: 这种转换的正确方式是什么?
问题内容: 我已经看到了很多类似的问题,但是还没有找到解决我特定问题的方法。我正在尝试SWIGify一些使用std :: function的C ++ 11代码,因此可以在Java应用程序中使用它。 我遇到了这样的共享指针: 并使用shared_ptr指令成功处理了它们,如下所示: 我遇到了像这样的共享指针向量: 并使用如下模板成功处理了它们: 现在我有一个这样的方法: 而且我无法让SWIG正确包装
我正在尝试为C中的以下函数创建JNI包装器: -输入,-输出 -输入,-输出 其中,定义为: 我完全沉浸在Java的SWIG手册中,因为它不只是支持输入参数作为输出类型。我对Python包装器没有任何问题(如下所示)。