如何为 Python 使用 SWIG 正确包装 std::vector<std::size_t>? std::size_t 的问题
How to properly wrap std::vector<std::size_t> with SWIG for Python? Problems with std::size_t
我正在尝试让 std::vector<std::size_t>
与 SWIG 一起工作。我需要为 C++ 库提供一个 python 接口。 std::vector
基本类型和对象工作正常,但 std::size_t
有问题。
我在 github here.
上提供了一个 MCVE
主要问题
基本上问题是 std::size_t
未被识别,std::vector<std::size_t>
被视为 std::vector< int,std::allocator< int > > *
。当我尝试指定模板时,我得到以下信息。
使用 %template(VecSize) std::vector<std::size_t>;
得到:
swig -c++ -python c_swig_vec_std_size.i
:0: Warning(490): Fragment 'SWIG_AsVal_std_size_t' not found.
:0: Warning(490): Fragment 'SWIG_From_std_size_t' not found.
g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
c_swig_vec_std_size_wrap.cxx: In static member function ‘static int swig::traits_asval<long unsigned int>::asval(PyObject*, swig::traits_asval::value_type*)’:
c_swig_vec_std_size_wrap.cxx:4289: error: ‘SWIG_AsVal_std_size_t’ was not declared in this scope
c_swig_vec_std_size_wrap.cxx: In static member function ‘static PyObject* swig::traits_from<long unsigned int>::from(const swig::traits_from::value_type&)’:
c_swig_vec_std_size_wrap.cxx:4295: error: ‘SWIG_From_std_size_t’ was not declared in this scope
make: *** [c] Error 1
最小示例
示例 C++ class
以下class足以显示我需要的功能。包含 std::vector<int>
以显示预期的行为。
class_vec_std_size.hpp
#ifndef STD_SIZE_VEC
#define STD_SIZE_VEC
#include <vector>
class StdSizeVec{
public:
StdSizeVec(){
_myVec = std::vector<std::size_t>();
_myVec.push_back(1);
_myVec.push_back(2);
_myInts = std::vector<int>();
_myInts.push_back(1);
_myInts.push_back(2);
}
~StdSizeVec(){
_myVec.clear();
}
inline std::vector<std::size_t> getValues(){
return _myVec;
}
inline std::vector<int> getInts(){
return _myInts;
}
private:
std::vector<std::size_t> _myVec;
std::vector<int> _myInts;
};
#endif
界面的各种尝试
a_swig_vec_std_size.i
%module a_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "class_vec_std_size.hpp"
输出
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from a_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t > *' at 0x2ad7047be330>
>>> ints = ssv.getInts()
>>> ints
<Swig Object of type 'std::vector< int > *' at 0x2ad7047be780>
>>> exit()
swig/python detected a memory leak of type 'std::vector< int > *', no destructor found.
swig/python detected a memory leak of type 'std::vector< std::size_t > *', no destructor found.
[paul@login-0-0 stack_swig]$
这是基本的幼稚方法。指针在 python 中没有用,并且存在我们无法向接口用户公开的内存泄漏消息。
b_swig_vec_std_size.i
%module b_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%include "class_vec_std_size.hpp"
输出
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from b_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t,std::allocator< std::size_t > > *' at 0x2aee17458330>
>>> ints = ssv.getInts()
>>> ints
<Swig Object of type 'std::vector< int,std::allocator< int > > *' at 0x2aee17458930>
>>> exit()
swig/python detected a memory leak of type 'std::vector< int,std::allocator< int > > *', no destructor found.
swig/python detected a memory leak of type 'std::vector< std::size_t,std::allocator< std::size_t > > *', no destructor found.
使用正确的 "std_vector.i",SWIG 对向量和分配器了解更多,但这些指针对 python 中的客户端代码仍然没有用,并且存在内存泄漏错误消息。
c_swig_vec_std_size.i
此接口使用正确的 %template
指令,如 this answer。这里 SWIG 不理解 std::size_t
作为模板参数。
%module c_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
// Does not compile
//%template(VecSize) std::vector<std::size_t>;
//
// Gives the following errors
//swig -c++ -python c_swig_vec_std_size.i
// :0: Warning(490): Fragment 'SWIG_AsVal_std_size_t' not found.
// :0: Warning(490): Fragment 'SWIG_From_std_size_t' not found.
// g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
// c_swig_vec_std_size_wrap.cxx: In static member function ‘static int swig::traits_asval<long unsigned int>::asval(PyObject*, swig::traits_asval::value_type*)’:
// c_swig_vec_std_size_wrap.cxx:4289: error: ‘SWIG_AsVal_std_size_t’ was not declared in this scope
// c_swig_vec_std_size_wrap.cxx: In static member function ‘static PyObject* swig::traits_from<long unsigned int>::from(const swig::traits_from::value_type&)’:
// c_swig_vec_std_size_wrap.cxx:4295: error: ‘SWIG_From_std_size_t’ was not declared in this scope
// make: *** [c] Error 1
//The following compiles but does not work
%template(VecSize) std::vector<size_t>;
%include "class_vec_std_size.hpp"
输出
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from c_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t,std::allocator< std::size_t > > *' at 0x2b286104bd80>
>>> ints = ssv.getInts()
>>> ints
(1, 2)
>>> exit()
swig/python detected a memory leak of type 'std::vector< std::size_t,std::allocator< std::size_t > > *', no destructor found.
现在 std::vector<int>
可以正常工作,但是 SWIG 的 %template(VecSize) std::vector<size_t>;
(没有 std::
)无法正常工作。
一些网络挖掘
我找到了一些提供了一些线索的帖子。
感觉像this I found a 2006 post with the same problem
std::vector::size_type wrapped as a pointer not an integer link 提供了一些有用的信息,但问题并不完全相同。
我从 magnum.fe 项目中找到了这个 primitives.i,但一厢情愿地导入 primitives.i 对我不起作用。
之后我尝试实现与他们的方法类似的SWIG_AsVal_std_size_t
和SWIG_From_std_size_t
,但没有成功。
手卷std_size_t.i
%fragment("SWIG_From_std_size_t", "header", fragment=SWIG_From_frag(std::size_t))
{
SWIGINTERNINLINE PyObject * SWIG_From_std_size_t(std::size_t value)
{
return PyInt_FromSize_t(value);
}
}
%fragment("SWIG_AsVal_std_size_t", "header")
{
SWIGINTERNINLINE bool SWIG_AsVal_std_size_t(PyObject* in, std::size_t& value)
{
// Get integer type
if(PyInt_Check(in)){
long unsigned int long_uint = PyLong_AsLong(in);
value = static_cast<std::size_t>(long_uint);
return true;
}else{
return false;
}
}
}
%fragment(SWIG_From_frag(std::size_t));
%fragment("SWIG_AsVal_std_size_t");
这是在 d_swig_vec_std_size.i 中导入的。但它无法编译。
%module d_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
%include "std_size_t.i"
%template(VecSize) std::vector<std::size_t>;
%include "class_vec_std_size.hpp"
我明白了。
swig -c++ -python d_swig_vec_std_size.i
g++ -fpic -c d_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
d_swig_vec_std_size_wrap.cxx: In static member function ‘static int swig::traits_asval<long unsigned int>::asval(PyObject*, swig::traits_asval::value_type*)’:
d_swig_vec_std_size_wrap.cxx:4311: error: invalid initialization of reference of type ‘size_t&’ from expression of type ‘swig::traits_asval::value_type*’
d_swig_vec_std_size_wrap.cxx:4288: error: in passing argument 2 of ‘bool SWIG_AsVal_std_size_t(PyObject*, size_t&)’
make: *** [d] Error 1
生成文件
PYTHON=/public/users/paul/dev/software/Python-2.7.11
all: a b c d
a:
swig -c++ -python a_swig_vec_std_size.i
g++ -fpic -c a_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared a_swig_vec_std_size_wrap.o -o _a_swig_vec_std_size.so
b:
swig -c++ -python b_swig_vec_std_size.i
g++ -fpic -c b_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared b_swig_vec_std_size_wrap.o -o _b_swig_vec_std_size.so
c:
swig -c++ -python c_swig_vec_std_size.i
g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared c_swig_vec_std_size_wrap.o -o _c_swig_vec_std_size.so
d:
swig -c++ -python d_swig_vec_std_size.i
g++ -fpic -c d_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared d_swig_vec_std_size_wrap.o -o _d_swig_vec_std_size.so
clean: clean_a clean_b clean_c clean_d
clean_a:
rm a_swig_vec_std_size_wrap.cxx a_swig_vec_std_size.py a_swig_vec_std_size_wrap.o _a_swig_vec_std_size.so
clean_b:
rm b_swig_vec_std_size_wrap.cxx b_swig_vec_std_size.py b_swig_vec_std_size_wrap.o _b_swig_vec_std_size.so
clean_c:
rm c_swig_vec_std_size_wrap.cxx c_swig_vec_std_size.py c_swig_vec_std_size_wrap.o _c_swig_vec_std_size.so
clean_d:
rm d_swig_vec_std_size_wrap.cxx d_swig_vec_std_size.py d_swig_vec_std_size_wrap.o _d_swig_vec_std_size.so
程序版本
python version: Python 2.7.11
g++ version: g++ (GCC) 4.4.7
swig version: SWIG Version 1.3.40
使用较新的 swig 版本 (swig-3.0.10) 对我来说是相同的结果。
总结
我怀疑答案可能与 interface d 某处类似,但到目前为止我运气不好。 std::size_t
的实现方式可能会因体系结构不同而不是固定大小而存在问题。无论如何,我希望 SWIG 能够处理它。我错过了什么吗?我想找到一个不涉及更改 C++ 库的解决方案(例如将 std::size_t 封装在 struct
中或改用 int
)。
尝试 Jens Monk 的解决方案
namespace std {
%template(VecSize) vector<size_t>;
}
我明白了:
[paul@login-0-0 stack_swig]$ make clean
rm a_swig_vec_std_size_wrap.cxx a_swig_vec_std_size.py a_swig_vec_std_size_wrap.o _a_swig_vec_std_size.so
rm b_swig_vec_std_size_wrap.cxx b_swig_vec_std_size.py b_swig_vec_std_size_wrap.o _b_swig_vec_std_size.so
rm c_swig_vec_std_size_wrap.cxx c_swig_vec_std_size.py c_swig_vec_std_size_wrap.o _c_swig_vec_std_size.so
rm d_swig_vec_std_size_wrap.cxx d_swig_vec_std_size.py d_swig_vec_std_size_wrap.o _d_swig_vec_std_size.so
[paul@login-0-0 stack_swig]$ make
swig -c++ -python a_swig_vec_std_size.i
g++ -fpic -c a_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared a_swig_vec_std_size_wrap.o -o _a_swig_vec_std_size.so
swig -c++ -python b_swig_vec_std_size.i
g++ -fpic -c b_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared b_swig_vec_std_size_wrap.o -o _b_swig_vec_std_size.so
swig -c++ -python c_swig_vec_std_size.i
g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared c_swig_vec_std_size_wrap.o -o _c_swig_vec_std_size.so
swig -c++ -python -I/public/users/paul/dev/software/swig-3.0.10 d_swig_vec_std_size.i
g++ -fpic -c d_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared d_swig_vec_std_size_wrap.o -o _d_swig_vec_std_size.so
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from d_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t,std::allocator< std::size_t > > *' at 0x2aba7dd8bd80>
>>> ints - ssv.getInts()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'ints' is not defined
>>> ints = ssv.getInts()
>>> ints
(1, 2)
>>> exit()
swig/python detected a memory leak of type 'std::vector< std::size_t,std::allocator< std::size_t > > *', no destructor found.
[paul@login-0-0 stack_swig]$ cat d_swig_vec_std_size.i
%module d_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
%include "std_size_t.i"
namespace std {
%template(VecSize) vector<size_t>;
}
%include "class_vec_std_size.hpp"
按如下方式实例化您的模板
namespace std {
%template(VecSize) vector<size_t>;
}
此更改适用于此处 - 开箱即用。我正在使用 SWIG 3.0.2、g++ 4.9.2 和 Python 2.7.9。
我已经更改了您的项目中的 d_swig_vec_std_size.i
以及您的 makefile 中 /usr/include/python2.7
的包含路径
%module d_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
%include "std_size_t.i"
namespace std {
%template(VecSize) vector<size_t>;
}
%include "class_vec_std_size.hpp"
尝试为 swig 定义 size_t,如此处所示 - http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn20
%inline %{
typedef long unsigned int size_t;
%}
namespace std {
%template(VecSize) vector<size_t>;
}
我正在尝试让 std::vector<std::size_t>
与 SWIG 一起工作。我需要为 C++ 库提供一个 python 接口。 std::vector
基本类型和对象工作正常,但 std::size_t
有问题。
我在 github here.
上提供了一个 MCVE主要问题
基本上问题是 std::size_t
未被识别,std::vector<std::size_t>
被视为 std::vector< int,std::allocator< int > > *
。当我尝试指定模板时,我得到以下信息。
使用 %template(VecSize) std::vector<std::size_t>;
得到:
swig -c++ -python c_swig_vec_std_size.i
:0: Warning(490): Fragment 'SWIG_AsVal_std_size_t' not found.
:0: Warning(490): Fragment 'SWIG_From_std_size_t' not found.
g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
c_swig_vec_std_size_wrap.cxx: In static member function ‘static int swig::traits_asval<long unsigned int>::asval(PyObject*, swig::traits_asval::value_type*)’:
c_swig_vec_std_size_wrap.cxx:4289: error: ‘SWIG_AsVal_std_size_t’ was not declared in this scope
c_swig_vec_std_size_wrap.cxx: In static member function ‘static PyObject* swig::traits_from<long unsigned int>::from(const swig::traits_from::value_type&)’:
c_swig_vec_std_size_wrap.cxx:4295: error: ‘SWIG_From_std_size_t’ was not declared in this scope
make: *** [c] Error 1
最小示例
示例 C++ class
以下class足以显示我需要的功能。包含 std::vector<int>
以显示预期的行为。
class_vec_std_size.hpp
#ifndef STD_SIZE_VEC
#define STD_SIZE_VEC
#include <vector>
class StdSizeVec{
public:
StdSizeVec(){
_myVec = std::vector<std::size_t>();
_myVec.push_back(1);
_myVec.push_back(2);
_myInts = std::vector<int>();
_myInts.push_back(1);
_myInts.push_back(2);
}
~StdSizeVec(){
_myVec.clear();
}
inline std::vector<std::size_t> getValues(){
return _myVec;
}
inline std::vector<int> getInts(){
return _myInts;
}
private:
std::vector<std::size_t> _myVec;
std::vector<int> _myInts;
};
#endif
界面的各种尝试
a_swig_vec_std_size.i
%module a_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "class_vec_std_size.hpp"
输出
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from a_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t > *' at 0x2ad7047be330>
>>> ints = ssv.getInts()
>>> ints
<Swig Object of type 'std::vector< int > *' at 0x2ad7047be780>
>>> exit()
swig/python detected a memory leak of type 'std::vector< int > *', no destructor found.
swig/python detected a memory leak of type 'std::vector< std::size_t > *', no destructor found.
[paul@login-0-0 stack_swig]$
这是基本的幼稚方法。指针在 python 中没有用,并且存在我们无法向接口用户公开的内存泄漏消息。
b_swig_vec_std_size.i
%module b_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%include "class_vec_std_size.hpp"
输出
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from b_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t,std::allocator< std::size_t > > *' at 0x2aee17458330>
>>> ints = ssv.getInts()
>>> ints
<Swig Object of type 'std::vector< int,std::allocator< int > > *' at 0x2aee17458930>
>>> exit()
swig/python detected a memory leak of type 'std::vector< int,std::allocator< int > > *', no destructor found.
swig/python detected a memory leak of type 'std::vector< std::size_t,std::allocator< std::size_t > > *', no destructor found.
使用正确的 "std_vector.i",SWIG 对向量和分配器了解更多,但这些指针对 python 中的客户端代码仍然没有用,并且存在内存泄漏错误消息。
c_swig_vec_std_size.i
此接口使用正确的 %template
指令,如 this answer。这里 SWIG 不理解 std::size_t
作为模板参数。
%module c_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
// Does not compile
//%template(VecSize) std::vector<std::size_t>;
//
// Gives the following errors
//swig -c++ -python c_swig_vec_std_size.i
// :0: Warning(490): Fragment 'SWIG_AsVal_std_size_t' not found.
// :0: Warning(490): Fragment 'SWIG_From_std_size_t' not found.
// g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
// c_swig_vec_std_size_wrap.cxx: In static member function ‘static int swig::traits_asval<long unsigned int>::asval(PyObject*, swig::traits_asval::value_type*)’:
// c_swig_vec_std_size_wrap.cxx:4289: error: ‘SWIG_AsVal_std_size_t’ was not declared in this scope
// c_swig_vec_std_size_wrap.cxx: In static member function ‘static PyObject* swig::traits_from<long unsigned int>::from(const swig::traits_from::value_type&)’:
// c_swig_vec_std_size_wrap.cxx:4295: error: ‘SWIG_From_std_size_t’ was not declared in this scope
// make: *** [c] Error 1
//The following compiles but does not work
%template(VecSize) std::vector<size_t>;
%include "class_vec_std_size.hpp"
输出
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from c_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t,std::allocator< std::size_t > > *' at 0x2b286104bd80>
>>> ints = ssv.getInts()
>>> ints
(1, 2)
>>> exit()
swig/python detected a memory leak of type 'std::vector< std::size_t,std::allocator< std::size_t > > *', no destructor found.
现在 std::vector<int>
可以正常工作,但是 SWIG 的 %template(VecSize) std::vector<size_t>;
(没有 std::
)无法正常工作。
一些网络挖掘
我找到了一些提供了一些线索的帖子。
感觉像this I found a 2006 post with the same problem
std::vector::size_type wrapped as a pointer not an integer link 提供了一些有用的信息,但问题并不完全相同。
我从 magnum.fe 项目中找到了这个 primitives.i,但一厢情愿地导入 primitives.i 对我不起作用。
之后我尝试实现与他们的方法类似的SWIG_AsVal_std_size_t
和SWIG_From_std_size_t
,但没有成功。
手卷std_size_t.i
%fragment("SWIG_From_std_size_t", "header", fragment=SWIG_From_frag(std::size_t))
{
SWIGINTERNINLINE PyObject * SWIG_From_std_size_t(std::size_t value)
{
return PyInt_FromSize_t(value);
}
}
%fragment("SWIG_AsVal_std_size_t", "header")
{
SWIGINTERNINLINE bool SWIG_AsVal_std_size_t(PyObject* in, std::size_t& value)
{
// Get integer type
if(PyInt_Check(in)){
long unsigned int long_uint = PyLong_AsLong(in);
value = static_cast<std::size_t>(long_uint);
return true;
}else{
return false;
}
}
}
%fragment(SWIG_From_frag(std::size_t));
%fragment("SWIG_AsVal_std_size_t");
这是在 d_swig_vec_std_size.i 中导入的。但它无法编译。
%module d_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
%include "std_size_t.i"
%template(VecSize) std::vector<std::size_t>;
%include "class_vec_std_size.hpp"
我明白了。
swig -c++ -python d_swig_vec_std_size.i
g++ -fpic -c d_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
d_swig_vec_std_size_wrap.cxx: In static member function ‘static int swig::traits_asval<long unsigned int>::asval(PyObject*, swig::traits_asval::value_type*)’:
d_swig_vec_std_size_wrap.cxx:4311: error: invalid initialization of reference of type ‘size_t&’ from expression of type ‘swig::traits_asval::value_type*’
d_swig_vec_std_size_wrap.cxx:4288: error: in passing argument 2 of ‘bool SWIG_AsVal_std_size_t(PyObject*, size_t&)’
make: *** [d] Error 1
生成文件
PYTHON=/public/users/paul/dev/software/Python-2.7.11
all: a b c d
a:
swig -c++ -python a_swig_vec_std_size.i
g++ -fpic -c a_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared a_swig_vec_std_size_wrap.o -o _a_swig_vec_std_size.so
b:
swig -c++ -python b_swig_vec_std_size.i
g++ -fpic -c b_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared b_swig_vec_std_size_wrap.o -o _b_swig_vec_std_size.so
c:
swig -c++ -python c_swig_vec_std_size.i
g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared c_swig_vec_std_size_wrap.o -o _c_swig_vec_std_size.so
d:
swig -c++ -python d_swig_vec_std_size.i
g++ -fpic -c d_swig_vec_std_size_wrap.cxx -I${PYTHON}/Include -I${PYTHON}
g++ -g -fpic -shared d_swig_vec_std_size_wrap.o -o _d_swig_vec_std_size.so
clean: clean_a clean_b clean_c clean_d
clean_a:
rm a_swig_vec_std_size_wrap.cxx a_swig_vec_std_size.py a_swig_vec_std_size_wrap.o _a_swig_vec_std_size.so
clean_b:
rm b_swig_vec_std_size_wrap.cxx b_swig_vec_std_size.py b_swig_vec_std_size_wrap.o _b_swig_vec_std_size.so
clean_c:
rm c_swig_vec_std_size_wrap.cxx c_swig_vec_std_size.py c_swig_vec_std_size_wrap.o _c_swig_vec_std_size.so
clean_d:
rm d_swig_vec_std_size_wrap.cxx d_swig_vec_std_size.py d_swig_vec_std_size_wrap.o _d_swig_vec_std_size.so
程序版本
python version: Python 2.7.11
g++ version: g++ (GCC) 4.4.7
swig version: SWIG Version 1.3.40
使用较新的 swig 版本 (swig-3.0.10) 对我来说是相同的结果。
总结
我怀疑答案可能与 interface d 某处类似,但到目前为止我运气不好。 std::size_t
的实现方式可能会因体系结构不同而不是固定大小而存在问题。无论如何,我希望 SWIG 能够处理它。我错过了什么吗?我想找到一个不涉及更改 C++ 库的解决方案(例如将 std::size_t 封装在 struct
中或改用 int
)。
尝试 Jens Monk 的解决方案
namespace std {
%template(VecSize) vector<size_t>;
}
我明白了:
[paul@login-0-0 stack_swig]$ make clean
rm a_swig_vec_std_size_wrap.cxx a_swig_vec_std_size.py a_swig_vec_std_size_wrap.o _a_swig_vec_std_size.so
rm b_swig_vec_std_size_wrap.cxx b_swig_vec_std_size.py b_swig_vec_std_size_wrap.o _b_swig_vec_std_size.so
rm c_swig_vec_std_size_wrap.cxx c_swig_vec_std_size.py c_swig_vec_std_size_wrap.o _c_swig_vec_std_size.so
rm d_swig_vec_std_size_wrap.cxx d_swig_vec_std_size.py d_swig_vec_std_size_wrap.o _d_swig_vec_std_size.so
[paul@login-0-0 stack_swig]$ make
swig -c++ -python a_swig_vec_std_size.i
g++ -fpic -c a_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared a_swig_vec_std_size_wrap.o -o _a_swig_vec_std_size.so
swig -c++ -python b_swig_vec_std_size.i
g++ -fpic -c b_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared b_swig_vec_std_size_wrap.o -o _b_swig_vec_std_size.so
swig -c++ -python c_swig_vec_std_size.i
g++ -fpic -c c_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared c_swig_vec_std_size_wrap.o -o _c_swig_vec_std_size.so
swig -c++ -python -I/public/users/paul/dev/software/swig-3.0.10 d_swig_vec_std_size.i
g++ -fpic -c d_swig_vec_std_size_wrap.cxx -I/public/users/paul/dev/software/Python-2.7.11/Include -I/public/users/paul/dev/software/Python-2.7.11
g++ -g -fpic -shared d_swig_vec_std_size_wrap.o -o _d_swig_vec_std_size.so
[paul@login-0-0 stack_swig]$ python
Python 2.7.11 (default, May 7 2016, 23:37:19)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from d_swig_vec_std_size import StdSizeVec
>>> ssv = StdSizeVec()
>>> vals = ssv.getValues()
>>> vals
<Swig Object of type 'std::vector< std::size_t,std::allocator< std::size_t > > *' at 0x2aba7dd8bd80>
>>> ints - ssv.getInts()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'ints' is not defined
>>> ints = ssv.getInts()
>>> ints
(1, 2)
>>> exit()
swig/python detected a memory leak of type 'std::vector< std::size_t,std::allocator< std::size_t > > *', no destructor found.
[paul@login-0-0 stack_swig]$ cat d_swig_vec_std_size.i
%module d_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
%include "std_size_t.i"
namespace std {
%template(VecSize) vector<size_t>;
}
%include "class_vec_std_size.hpp"
按如下方式实例化您的模板
namespace std {
%template(VecSize) vector<size_t>;
}
此更改适用于此处 - 开箱即用。我正在使用 SWIG 3.0.2、g++ 4.9.2 和 Python 2.7.9。
我已经更改了您的项目中的 d_swig_vec_std_size.i
以及您的 makefile 中 /usr/include/python2.7
的包含路径
%module d_swig_vec_std_size
%{
#include "class_vec_std_size.hpp"
%}
%include "std_vector.i"
%template(VecInt) std::vector<int>;
%include "std_size_t.i"
namespace std {
%template(VecSize) vector<size_t>;
}
%include "class_vec_std_size.hpp"
尝试为 swig 定义 size_t,如此处所示 - http://www.swig.org/Doc1.3/SWIG.html#SWIG_nn20
%inline %{
typedef long unsigned int size_t;
%}
namespace std {
%template(VecSize) vector<size_t>;
}