我有以下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
有什么想念我的东西吗?
答案 0 :(得分:1)
[Python 3]: ctypes - A foreign function library for 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.