我使用SWIG包装2个C ++对象,我在我的应用程序中嵌入Python解释器(即自己调用PyInitialize()等)。
第一个对象是某些应用程序数据的包装器。 第二个是帮助" object,也是用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"实际上是一些可能的派生类的基类。我的帮助对象想要在它接收的指针上执行适当的(由上下文确定)动态转换,以指向适当的派生类。我现在认为这是不明智的原因。
我已经读过一些关于" shadow" SWIG中的对象,只会增加我的困惑(为我的小脑道歉:-P)
那么,SWIG是出于某种原因制作了我的对象的副本,然后将指针传递给副本?如果是,那么我就能理解为什么我对动态演员的假设不起作用。
我试图将此作为评论添加,但在格式化方面遇到了困难,所以......更多见解如下: 问题与传递引用有关。注意我有2个虚拟方法helpMe()的实现:
bool MyHelperObject::helpMe(MyDataObject mydata_obj)
{
return common_code(&mydata_obj);
}
bool MyHelperObject::helpMe(MyDataObject *mydata_obj)
{
return common_code(mydata_obj);
}
虽然我为python提供了一个指针,但它正在调用pass-by-reference版本。这就解释了为什么我得到不同的指针值。但是我可以做什么来强制调用带有指针参数的版本?
答案 0 :(得分:1)
根据您展示的内容,我认为您希望确保SWIG只能看到helpMe
的指针版本。非指针版本将创建一个临时副本,然后将其传递给函数,听起来这不是你想要的。
SWIG将很难选择使用哪个版本,因为它会略微抽象指针概念以更好地匹配Python。
您可以在声明之前使用%ignore
隐藏SWIG中的非指针版本,或者在接口文件中将其显示为SWIG的%import
:
%ignore MyHelperObject::helpMe(MyDataObject mydata_obj)
%import "some.h"