无法映射到向量 <std::string>
Trouble mapping to vector<std::string>
我正在尝试为第三方库扩展 python 包装器。我是 swig 的新手,对 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 指令,可能是由于类型参数中的 "allocator"。
事实上,如果我查看这个函数的 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 列表?
What is the allocator...
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;
...how do I get swig to map the vector to a python list
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'
我正在尝试为第三方库扩展 python 包装器。我是 swig 的新手,对 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 指令,可能是由于类型参数中的 "allocator"。
事实上,如果我查看这个函数的 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 列表?
What is the allocator...
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;
...how do I get swig to map the vector to a python list
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'