我试图为第三方库扩展python包装器。我很开心并且在c ++上相当生气,所以任何帮助都会受到赞赏。
swig接口文件的代码如下:
%include "std_list.i"
%include "std_map.i"
%include "std_vector.i"
%include "std_string.i"
%include "std_pair.i"
%include "std_shared_ptr.i"
%shared_ptr(std::vector<std::string>)
%define VECTORTEMPLATE_WRAP(vectorname, T)
%feature("ignore") vector<T>::append;
// a bunch more %feature("ignore")
%template(vector ## vectorname) vector<T>;
%enddef
VECTORTEMPLATE_WRAP(String, std::string)
我认为最后一部分只是一种更通用的说法
%template(vectorString) vector<std::string>
然后在头文件中声明此函数:
class OBCONV OBConversion
{
int FullConvert(std::vector<std::string>& FileList, std::string&
OutputFileName, std::vector<std::string>& OutputFileList);
}
然而,当我构建整个项目并在python中调用此函数时:
conv = ob.OBConversion()
conv.FullConvert([],'',[])
我收到以下错误:
TypeError: in method 'OBConversion_FullConvert', argument 2 of type 'std::vector< std::string,std::allocator< std::string > > &'
在我看来,完全跳过%template指令,可能是因为&#34; allocator&#34;在类型参数中。
确实,如果我查看swig生成的c ++代码,我有
SWIGINTERN PyObject *_wrap_OBConversion_FullConvert(PyObject
*SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0;
OpenBabel::OBConversion *arg1 = (OpenBabel::OBConversion *) 0 ;
std::vector< std::string,std::allocator< std::string > > *arg2 = 0 ;
std::string *arg3 = 0 ;
std::vector< std::string,std::allocator< std::string > > *arg4 = 0 ;
// ...
}
我使用c ++ 11构建,我不认为该项目最初是为此开发的,因此可能与它有关。
什么是分配器,如何让swig将矢量映射到python列表?
答案 0 :(得分:0)
什么是分配器...
std::string
实际上是std::basic_string<char>
,其定义如下,并且具有Traits
和Allocator
的默认实现。 SWIG只显示这些默认值。
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> class basic_string;
...如何让swig将矢量映射到python列表
SWIG并不自动知道如何将Python列表转换为stringVector
。您可以获得一些免费功能(如下所示),或者您必须编写其他类型图以告知SWIG如何将Python列表转换为向量。
这是一个使用字符串向量的Windows工作示例。注意使用const
正确帮助SWIG知道使用输入类型映射与输出类型映射,我的示例有一个输入向量和字符串以及输出向量:
<强> test.h 强>
#include <vector>
#include <string>
#ifdef API_EXPORTS
# define API __declspec(dllexport)
#else
# define API __declspec(dllimport)
#endif
API int FullConvert(const std::vector<std::string>& FileList, const std::string& OutputFileName, std::vector<std::string>& OutputFileList);
<强> TEST.CPP 强>
#include <iostream>
#include <vector>
#include <string>
#define API_EXPORTS
#include "test.h"
// Example to copy vin to vout
API int FullConvert(const std::vector<std::string>& FileList, const std::string& OutputFileName, std::vector<std::string>& OutputFileList)
{
for(auto& file: FileList)
{
std::cout << file << std::endl;
OutputFileList.push_back(file);
}
std::cout << OutputFileName << std::endl;
return 1;
}
<强> test.i 强>
%module test
%{
#include "test.h"
%}
%include <windows.i>
%include <std_vector.i>
%include <std_string.i>
%template(stringVector) std::vector<std::string>;
%include "test.h"
<强>输出强>
>>> import test
>>> vin = test.stringVector()
>>> vout = test.stringVector()
>>> vin.push_back('abc')
>>> vin.push_back('def')
>>> test.FullConvert(vin,'test',vout)
abc
def
test
1
>>> vout[0]
'abc'
>>> vout[1]
'def'