麻烦映射到vector <std :: string>

时间:2017-12-21 22:44:20

标签: python c++11 swig

我试图为第三方库扩展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列表?

1 个答案:

答案 0 :(得分:0)

  

什么是分配器...

std::string实际上是std::basic_string<char>,其定义如下,并且具有TraitsAllocator的默认实现。 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'