【发布时间】: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++ 接口(具有完整但最小的实现)是什么样的?我对你的想法有一个想法,但我宁愿在我知道我们都在同一页上之前不花时间回答。