我有以下 C 代码,我将从 python 脚本中使用它。
这只是自动生成的巨大库的摘录,不幸的是我无法更改它。在这里,我只是想将结构元素打印到控制台来演示出了什么问题。
// CFunc.h
#include <stdio.h>
typedef struct
{
int npar;
struct
{
int id;
int value;
} params[10];
} Data_t;
void Cfunc( const Data_t * d);
// CFunc.c
#include "CFunc.h"
void Cfunc( const Data_t * d)
{
int inpar = 0;
int maxnpar = 0;
printf("%d:\n", d->npar);
maxnpar = d->npar;
inpar=0;
while (maxnpar > inpar)
{
printf(" %d: %08x %08x\n", inpar, d->params[inpar].id, *(int*)&d->params[inpar].value);
inpar++;
}
}
它被编译并链接到共享库:
gcc -fPIC -c CFunc.c -o CFunc.o
gcc -shared -lrt -Wl,-soname,libCFunc.so.1 -o libCFunc.so CFunc.o
所以我使用 ctypes 进行了以下实现:
from ctypes import *
lib = CDLL('./libCFunc.so')
class Data_2(Structure):
pass
class Data_t(Structure):
def __init__(self, list):
self.npar = len(list)
self.params = (Data_2 * self.npar)(*list)
Data_2._fields_ = [
('id', c_int),
('value', c_int),
]
Data_t._fields_ = [
('npar', c_int),
('params', POINTER(Data_2)),
]
def pyFunc(d):
lib.Cfunc.argtypes = (POINTER(Data_t),)
lib.Cfunc(byref(d))
return
因此,我从给定元组列表中初始化该结构,在本例中只有 2 个元组,并调用 C 函数来查看其输出。
paramlist = (
( 0x050000000, 0x00000000 ),
( 0x050000001, 0x447a0000 ) )
temp = Data_t(paramlist)
pyFunc(temp)
不幸的是,输出不符合预期:
2:
0: 00000000 79948ef0
1: 00007fe5 00000000
有什么想法我错过了什么吗?
最佳答案
[Python 3]: ctypes - A foreign function library for Python .
- C 和 Python 的结构不匹配
- params是数组而不是指针
- 由于上述不一致,您使 Python 中的事情变得过于复杂:
- 您没有不完整的类型,因此您的结构可以静态定义
我稍微重组了你的代码。
dll.h:
#pragma once
typedef struct Data_ {
int npar;
struct
{
int id;
int value;
} params[10];
} Data;
void test(const Data *d);
dll.c:
#include "dll.h"
#include <stdio.h>
void test(const Data *d) {
int inpar = 0;
int maxnpar = 0;
printf("%d:\n", d->npar);
maxnpar = d->npar;
inpar = 0;
while (inpar < maxnpar)
{
printf(" %d: %08x %08x\n", inpar, d->params[inpar].id, *(int*)&d->params[inpar].value);
inpar++;
}
}
code.py:
#!/usr/bin/env python3
import sys
import ctypes
DLL = "./libdll.so"
class DataInner(ctypes.Structure):
_fields_ = [
("id", ctypes.c_int),
("value", ctypes.c_int),
]
DataInnerArr10 = DataInner * 10
class Data(ctypes.Structure):
_fields_ = [
("npar", ctypes.c_int),
("params", DataInnerArr10),
]
def __init__(self, data):
self.npar = len(data)
self.params = DataInnerArr10(*data)
def main():
dll_dll = ctypes.CDLL(DLL)
test_func = dll_dll.test
test_func.argtypes = [ctypes.POINTER(Data)]
param_list = (
(0x050000000, 0x00000000),
(0x050000001, 0x447a0000),
)
d = Data(param_list)
test_func(ctypes.byref(d))
print("Done.")
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
输出:
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054888242]> ls code.py dll.c dll.h [cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054888242]> gcc -shared -fPIC -o libdll.so dll.c [cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054888242]> ls code.py dll.c dll.h libdll.so [cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054888242]> python3 code.py Python 3.6.4 (default, Jan 7 2018, 15:53:53) [GCC 6.4.0] on cygwin 2: 0: 50000000 00000000 1: 50000001 447a0000 Done.
关于python - 将带有数组的嵌套 ctypes 结构传递给 C 库函数不符合预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54888242/