【问题标题】:Reusing SWIG mappings in custom typemap在自定义类型映射中重用 SWIG 映射
【发布时间】: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 接口,所以易用性是决定因素。

标签: python c++ swig


【解决方案1】:

SWIG 实际上将一大堆运行时信息作为外部接口的一部分,有关详细信息,请参阅http://www.swig.org/Doc3.0/Modules.html#Modules_external_run_time。这包括您可能需要的功能。

我不同意您的评估,即在 Python 中将std::vector 映射到列表更清晰——您最终总是复制并访问该向量的每个成员来执行此操作。实际上,您复制了原始容器并最终得到了两个容器,因此对 Python 列表的更改不会反映在底层 C++ 容器上。 Python 提供的std::vector 包装应该实现您关心的协议以默认启用pythonic 语法,并且也可以正确支持ABCs ..(如果他们不这样做,我准备编写补丁!)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多