【发布时间】:2019-01-25 04:41:31
【问题描述】:
我目前正在为要使用 SWIG 的 C++ 库开发 Python 包装器。在我的 C++ 库中,我有一个具有以下签名的方法:
std::vector<SomeClass> getMembers();
现在我知道 SWIG 具有内置的 std::vector 支持,但我想将 std::vectors 显式转换为 Python 列表(我只是认为它更干净)。为此,我有以下类型映射:
template<typename T>
PyObject* toList(vector<T> vec){
size_t size = vec.size();
PyObject *o = PyList_New(size);
for(size_t i = 0; i < size; i++){
PyList_SetItem(o, i, toPythonInstance<T>(vec[i]));
}
return o;
}
%define OUTPUT_VEC_TO_LIST(type)
%typemap (out) std::vector<type> {
$result = toList<type>($1);
}
%enddef
现在是模板方法:
template<T>
PyObject* toPythonInstance(T& val){}
可以专门添加对必要数据类型的支持。我现在面临的问题如下:
SomeClass 由 SWIG 自动包装。所以我喜欢做的是在我的向量类型映射中重用这个包装器,即具有以下内容:
template<>
PyObject* toPythonInstance<SomeClass>(SomeClass& val){
//call some SWIG macro to automatically wrap the given instance to
//a Python object
}
查看 SWIG 生成的代码,我已经发现了以下函数
SWIG_NewPointerObj(...);
SWIG_ConvertPtr(...);
这似乎负责做我想做的事。但是,我不想干涉 SWIG 的任何内部结构。因此,如果有人知道如何使用“公共” SWIG 界面实现我想要的,我会非常高兴!
【问题讨论】:
-
您可能想查看pybind11.readthedocs.io/en/stable。它类似于 Swig,只要你能将 SomeClass 转换为 Python,它就会自动将 std::vector
转换为 Python 的列表。 -
您正在查看的函数不是私有内部函数 - 请参阅 swig.org/Doc3.0/Modules.html#Modules_external_run_time
-
@Flexo:这是我的问题的答案,所以如果你想把它写成一个,我很高兴接受它! :)
-
@sangrey:PyBind11 的建议非常完美!我尝试了它并决定开始使用它而不是 SWIG,因为它拥有我需要的一切,但比 SWIG 更易于使用 - 因为我只需要一个 Python 接口,所以易用性是决定因素。