我一直在网上搜索,没有运气。我有以下Python代码:
class LED(Structure):
_fields_ = [
('color', c_char_p),
('id', c_uint32)
]
class LEDConfiguration(Structure):
_fields_ = [
('daemon_user', c_char_p),
('leds', POINTER(LED)),
('num_leds', c_uint32)
]
这是一个使用这些结构并返回LEDConfiguration的简化示例函数。
def parseLedConfiguration(path, board):
lc = LEDConfiguration()
for config in configs:
if( config.attributes['ID'].value.lstrip().rstrip() == board ):
lc.daemon_user = c_char_p('some_name')
leds = []
#Imagine this in a loop
ld = LED()
ld.color = c_char_p('red')
ld.id = int(0)
leds.append(ld)
#end imagined loop
lc.num_leds = len(leds)
lc.leds = (LED * len(leds))(*leds)
return lc
现在这是我正在使用的C代码(我已经删除了涉及设置python /调用“parseLedConfiguration”函数/等的所有内容,但如果有帮助我可以添加它。)
/*Calling the python function "parseLedConfiguration"
pValue is the returned "LEDConfiguration" python Structure*/
pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
if (pValue != NULL)
{
int i, num_leds;
PyObject *obj = PyObject_GetAttr(pValue, PyString_FromString("daemon_user"));
daemon_user = PyString_AsString(obj);
Py_DECREF(obj);
obj = PyObject_GetAttr(pValue, PyString_FromString("num_leds"));
num_leds = PyInt_AsLong(obj);
Py_DECREF(obj);
obj = PyObject_GetAttr(pValue, PyString_FromString("leds"));
PyObject_Print(obj, stdout, 0);
我的问题是弄清楚如何访问返回到最终“obj”的内容。 “obj”上的“PyObject_Print”显示了这个输出:
<ConfigurationParser.LP_LED object at 0x7f678a06fcb0>
我想进入一个可以访问LP_LED对象的状态,就像我访问上面的“LEDConfiguration”对象一样。
编辑1
我想另一个可能更重要的问题是,我的python代码是否正确?这是我应该如何将“结构”的列表或数组存储在另一个“结构”中,以便可以从Python C API访问它?
谢谢!
答案 0 :(得分:1)
由于您的编辑1澄清了基本问题,让我把它放在最上面:
猜猜另一个可能更重要的问题,我的python代码是否正确?这是我应该如何将“结构”的列表或数组存储在另一个“结构”中,以便可以从Python C API访问它?
不,这就是你应该如何将Structure
数组存储在另一个Structure
中,以便可以从non-Python-C-API
C代码访问它。如果您希望从Python C API访问它,只需使用Python list
。
通常,如果您在Python和C中编写代码,则只有一方必须向后弯曲以与另一方一起工作。在Python中使用ctypes
Structure
和POINTER
等等的重点是允许他们在C中直接工作,而无需经历C API。相反,使用像PyList_GetItem
这样的函数的关键是允许你使用普通的Python代码,而不是ctypes
Python代码。
所以,如果你想在list
内存储一个Structure
来通过Python C API访问,只需存储一个Python list
- 你真的不需要Structure
首先是__slots__
;使用普通的Python类(可能使用ctypes
)。您可以编写此代码而无需导入ctypes
。
相反,如果要存储可以直接在C中使用的结构,可以使用Structure
执行此操作;然后,在C代码中,一旦你进入PyObject *
Cython
胆量,你不再需要Python API了,因为结构都是C.这通常是你去的方式当你有现有的C代码,并希望从Python接口时,而不是从头开始设计C代码,但是没有规则说你不能以其他方式使用它。
同时,如果这是您第一次尝试编写彼此交谈的C和Python代码,我建议您使用ctypes
。然后,如果您对此感到满意,如果您想学习ctypes
,请使用Python与ctypes
进行不同的项目,以便与对Python完全一无所知的C代码进行对话。然后,第三个使用C API与Python代码交谈的项目,该代码对PyList_GetItem
一无所知(与大多数C扩展模块一样)。一旦熟悉了这三个项目,您将来可以为大多数项目选择合适的项目。
现在,回答具体问题:
首先,当list
(或C API中的大多数其他函数)返回NULL时,这意味着存在异常,因此您应该检查异常并将其记录下来。尝试在不查看set异常的情况下调试C API中的NULL返回值就像尝试调试Python代码而不查看回溯一样。
无论如何,这个函数可能会失败有一些明显的原因:也许你用一个越界索引来调用它,或者你可能在一个不是obj
的东西上调用它一点都不。
事实上,第二个看起来非常明显。如果打印<ConfigurationParser.LP_LED object at 0x7f678a06fcb0>
给你这个:
LED
然后你有一个(指向一个)LED
对象的指针,list
个对象不是list
。
如果你查看你的代码,你似乎没有LED
个POINTER(LED)
个对象,至少在你给我们看的代码中没有。你有一个LED
,它可以容纳一个C-array衰变的list
的C数组,但这与它们的Python PyObject *led = ledarray[i];
不同。它只是一个C数组,您可以使用C数组语法取消引用:
{{1}}