如何在Python中为类类型应用SWIG OUTPUT类型映射?
我在使用SWIG(版本3.0.6)围绕C ++库生成Python包装程序时遇到了一些麻烦。
我的问题与应用OUTPUT类型映射有关,特别是在对类类型的指针/引用的情况下。
为了说明这一点,这是我想要的标准类型,它的工作原理是:
// .h
int add(const long arg1,const long arg2,long& resultLong);
// interface.i
%apply long& OUTPUT { long& resultLong };
int add(const long arg1,const long arg2,long& resultLong);
// projectWrapper.py
def add(arg1, arg2):
return _projectWrapper.add(arg1, arg2)
addTerm = _projectWrapper.add
// usage
>>> result = projectWrapper.add(2, 4)
>>> print result
[0, 6L]
您不必传递“ resultLong”,但会自动将其附加到结果中。大!
但是,当输出类型是指向类类型的某种指针时,这似乎不像我期望的那样工作:
// .h
int GetClassType(const char* name, exportedClassType*& resultPointer);
class exportedClassType
{...}
// interface.i
%apply exportedClassType*& OUTPUT { exportedClassType*& resultPointer };
int GetClassType(const char* name, exportedClassType*& resultPointer);
// projectWrapper.py
def GetClassType(name, resultPointer):
return _projectWrapper.GetClassType(name, resultPointer)
GetClassType = _projectWrapper.GetClassType
问题似乎在于SWIG并未以与简单类型相同的方式对其进行处理。它仍然在包装的函数签名中显示为“输入”参数。
// attempted usage
>>> classType = projectWrapper.GetClassType("name")
TypeError: GetClassType() takes exactly 2 arguments (1 given)
>>> result = 0
>>> projectWrapper.GetClassType("name", result)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: in method 'GetClassType', argument 2 of type 'exportedClassType *&'
有人可以告诉我我做错了什么,还是指出正确的方向吗?任何帮助表示感谢!谢谢
-
这个问题似乎已经解决了很长时间了,所以我认为我最好为这个问题提供解决方案。OUTPUT类型映射仅适用于简单类型,因此可以通过将
in
和类型argout
映射组合来提供解决方案。考虑一下这种情况,我们有一个
SampleImpl
实现C 接口的C
类SampleBase
,从技术上来说,它不是接口,因为它涉及虚拟析构函数的实现。假设我们有一个静态函数,该函数返回错误代码和接口的实现。后者是对指针的引用,这是上面的情况。接口头:
// Sample.hpp #pragma once namespace Module { class SampleBase { public: #ifndef SWIG // Hint to the programmer to implement this function static int SampleCreate(SampleBase *&obj); #endif virtual ~SampleBase() = default; }; }
实施标头:
// Sample_impl.hpp #pragma once #include "Sample.hpp" namespace Module { class SampleImpl : public SampleBase { public: static int SampleCreate(Module::SampleBase *&obj); SampleImpl(); virtual ~SampleImpl(); private: float a; }; }
实现方式:
// Sample_impl.cpp #include "Sample_impl.hpp" #include <cstdio> namespace Module { int SampleImpl::SampleCreate(Module::SampleBase*& obj) { obj = (SampleBase*) new SampleImpl(); return 0; } SampleImpl::SampleImpl() { printf("SampleImpl::SampleImpl()\n"); } SampleImpl::~SampleImpl() { printf("SampleImpl::~SampleImpl()\n"); } }
SWIG界面(使用argout类型映射)
// example.i %module example %{ #define SWIG_FILE_WITH_INIT #include "Sample.hpp" #include "Sample_impl.hpp" %} %include "typemaps.i" %typemap(in, numinputs=0) Module::SampleBase *&obj (Module::SampleBase *temp) { $1 = &temp; } %typemap(argout) Module::SampleBase *& { PyObject* temp = NULL; if (!PyList_Check($result)) { temp = $result; $result = PyList_New(1); PyList_SetItem($result, 0, temp); // Create shadow object (do not use SWIG_POINTER_NEW) temp = SWIG_NewPointerObj(SWIG_as_voidptr(*$1), $descriptor(Module::SampleBase*), SWIG_POINTER_OWN | 0); PyList_Append($result, temp); Py_DECREF(temp); } }
在Python中的用法
import example // Creating specialization obj = example.SampleImpl() del obj // Creation of object using output typemap errorCode, obj = example.SampleImpl_SampleCreate() del obj