【问题标题】:Using SWIG to pass C++ object pointers to Python, than back to C++ again使用 SWIG 将 C++ 对象指针传递给 Python,而不是再次返回 C++
【发布时间】:2014-04-18 23:32:47
【问题描述】:

我正在使用 SWIG 包装 2 个 C++ 对象,并将 Python 解释器嵌入到我的应用程序中(即自己调用 PyInitialize() 等)。

第一个对象是一些应用程序数据的包装器。 第二个是“帮助”对象,也是用 C++ 编写的,它可以根据在数据对象中找到的内容执行某些操作。

python 脚本决定何时/如何/是否调用辅助对象。

因此,我将指向我的 C++ 对象的指针传递给 SWIG/Python:

swig_type_info *ty = SWIG_MangledTypeQuery("_p_MyDataObject");
if(ty == NULL)
 {
    Py_Finalize();
     return false;
 }

PyObject *data_obj = SWIG_NewPointerObj(PointerToMyDataObject, ty, 0);
if(data_obj == NULL)
{
     Py_Finalize();
     return false;
}

ty = SWIG_MangledTypeQuery("_p_MyHelperObject");
 if(ty == NULL)
{
     Py_Finalize();
    return false;
 }

PyObject *helper_obj = SWIG_NewPointerObj(PointerToMyHelperObject, ty, 0);
if(helper_obj == NULL)
{
    Py_Finalize();
    return false;
}
PyTuple_SetItem(pArgs, 0, data_obj);
PyTuple_SetItem(pArgs, 1, helper_obj);
PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
if(pValue == NULL)
{
     Py_Finalize();
     return false;
}

在 Python 中,我们会看到如下内容:

def go(dataobj, helperobj):
    ## if conditions are right....
    helperobj.helpme(dataobj)

现在,除了一件事之外,这在很大程度上是可行的。在我的 C++ 代码中,当我准备将参数传递给 Python 脚本时,我观察到 PointerToMyDataObject 的指针值。

当我在 helperobj.helpme() 的 C++ 实现中设置断点时,我看到内存地址不同,尽管它似乎是指向有效 MyDataObject 实例的指针。

这对我很重要,因为“MyDataObject”实际上是一些可能的派生类的基类。我的助手对象想要对它接收到的指针执行适当的(由上下文确定)动态转换,以指向适当的派生类。失败的原因我认为现在很明显。

我在 SWIG 中阅读了一些关于“阴影”对象的内容,这只会增加我的困惑(为我的小脑袋道歉:-P)

那么,SWIG 是否出于某种原因复制了我的对象,然后将指针传递给该副本?如果是,那么我可以理解为什么我对动态转换的假设不起作用。

我尝试将此添加为评论,但在格式化方面遇到了困难,所以.....更多见解如下: 问题与传递引用有关。请注意,我有 2 个 virtual 方法 helpMe() 的实现:

bool MyHelperObject::helpMe(MyDataObject mydata_obj)
{
    return common_code(&mydata_obj);
}
bool MyHelperObject::helpMe(MyDataObject *mydata_obj)
{
    return common_code(mydata_obj);
}

虽然我为 python 提供了一个指针,但它调用的是传递引用版本。这解释了为什么我得到不同的指针值。但是我能做些什么来强制调用带有指针参数的版本呢?

【问题讨论】:

  • 您能否重新调整问题的焦点,以更清楚地显示您想要包装的 C++ 接口(具有完整但最小的实现)是什么样的?我对你的想法有一个想法,但我宁愿在我知道我们都在同一页上之前不花时间回答。

标签: python c++ pointers swig


【解决方案1】:

根据您所展示的内容,我认为您希望确保 SWIG 只能看到 helpMe 的指针版本。非指针版本将创建一个临时副本,然后将其传递给函数,听起来这不是你想要的。

SWIG 将很难选择使用哪个版本,因为它稍微抽象了指针概念以更好地匹配 Python。

您可以在声明之前使用%ignore%import 在接口文件中向 SWIG 隐藏非指针版本:

%ignore MyHelperObject::helpMe(MyDataObject mydata_obj)
%import "some.h"

【讨论】:

    猜你喜欢
    • 2016-09-15
    • 2022-09-24
    • 2021-08-01
    • 2022-01-08
    • 2012-02-05
    • 1970-01-01
    • 2010-09-20
    • 2019-01-28
    • 1970-01-01
    相关资源
    最近更新 更多