正如消息主题所说:我如何在C / C ++扩展模块中创建一个在Python代码中定义的类的新实例?我将在下面提供更多信息。< / p>
注意#1:我正在尝试使用Python / C API执行此操作,如下所示。但任何其他替代解决方案对我来说也是可以接受的〜)
我有一个Python文件,CppInterop.py:
import CppProxy
class RealTimeData:
def __init__(self, id, value):
self.id = id
self.value = value
def writeAll():
dataList= []
dataList.append(RealTimeData("ID::001", 1.0))
dataList.append(RealTimeData("ID::002", 2.0))
dataList.append(RealTimeData("ID::003", 3.0))
count = CppProxy.WriteRealTimeDataList(dataList)
print count
def readAll():
dataList = CppProxy.ReadRealTimeDataList() # Try to read the list back
for data in dataList:
print "id: ", data.id
print "value: ", data.value
pass
if __name__ == '__main__':
writeAll()
readAll()
在“ readAll ”函数中,我想将存储在C / C ++模块中的列表读回Python代码,然后打印每个元素。
预计从CppProxy返回的“dataList”是包含类RealTimeData 元素的列表(如开头所定义)。
为此,我认为在我的C / C ++模块扩展代码中,我需要创建一个PyList实例,然后创建一些RealTimeData实例。可能是这样的:
static
PyObject * ReadRealTimeDataList(PyObject * self, PyObject * args)
{
// Create a new Python list, size of which is zero.
PyObject * listObj = PyList_New(0);
if (NULL == listObj)
{
return NULL;
}
// Append some elements to the list
for (int i = 0; i < 3; ++i)
{
// How can I create a RealTimeData instance here and assign it to dataObj?
PyObject * dataObj;
PyObject * idObj = PyString_FromString("some id");
PyObject_SetAttrString(dataObj, "id", idObj);
PyObject * valueObj = PyFloat_FromDouble((double)i);
PyObject_SetAttrString(dataObj, "value", valueObj);
if (PyList_Append(listObj, dataObj) != 0)
{
// error!
return NULL;
}
}
// return the list object to Python part
return Py_BuildValue("O", listObj);
}
我读了this SO question。我是否需要执行与定义新的PyTypeObject以描述Python类RealTimeData相同的内容,然后创建它的新实例?
但我认为实际上从C ++代码中引入了一个新的类类型,而不是重用已经在Python代码中定义的类类型。
感谢任何帮助!
答案 0 :(得分:4)
Python定义的类在Python / C扩展中实例化,与Python完全相同:通过导入并调用类对象:
// obtain the RealTimeData class
PyObject *get_RealTimeData()
{
PyObject *module = PyImport_ImportModule("CppInterop");
if (!module)
return NULL;
return PyObject_GetAttrString(module, "RealTimeData");
}
static
PyObject *ReadRealTimeDataList(PyObject *self, PyObject *args)
{
static PyObject *RealTimeData = get_RealTimeData();
...
// instantiate the class like you would in Python - by
// calling the class object
dataObj = PyObject_CallFunction(RealTimeData, "sd", "some id", 0.0);
if (!dataObj)
return NULL;
...
}
几个不相关的说明:
RealReadTimeDataList
由于某种原因没有返回数据列表,而是一个保存列表的单元素元组。由于您的Python代码需要列表本身,因此只需返回listObj
。PyString_FromString
,PyFloat_FromDouble
或PyObject_SetAttrString
的结果。Py_DECREF(listObj)
失败时应调用PyList_Append
。如上所述,在这种情况下,代码会泄漏listObj
。