项目中现在遇到这么一个问题,函数是用 c 写的,调用要用到 python,因为是在 linux 环境,所以是直接调用的动态库 SO 文件,调用方式我已经搞定了,但是不知道怎么用 pyton 给 c 函数传递结构体参数,网上找了一些例子,但没调通,不知道是哪里不对,请教各位了,帖一下简单的代码例子:
//test1.c
# include <stdio.h>
# include <stdlib.h>
struct Student
{
char name[30];
float fScore[3];
};
void Display(struct Student su)
{
printf("-----Information------\n");
printf("Name:%s",su.name);
printf("Chinese:%.2f\n",su.fScore[0]);
printf("Math:%.2f\n",su.fScore[1]);
printf("English:%.2f",su.fScore[2]);
printf("平均分数为:%.2f\n",(su.fScore[0]+su.fScore[1],su.fScore[2])/3);
}
以上代码编辑成动态库 libpycall.so 文件了
gcc -o libpycall.so -shared -fPIC test1.c
python 调用 c 的代码:
#pycall.py
import ctypes
from ctypes import *
class Student(Structure):
_fields_ = [("param1",c_char_p),
("param2", c_float * 3)
]
su = Student()
su.param1 = b"testsdk"
PARAM = c_float * 3
param2 = PARAM()
param2[0] = 1.1
param2[1] = 1.2
param2[2] = 1.3
su.param2 = param2
if __name__ == '__main__':
ll = ctypes.cdll.LoadLibrary
lib = ll("./libpycall.so")
lib.Display(byref(su))
print('----- finish -----')
============================================================
我期望的结果是按以下代码执行
//test1_demo.c
# include <stdio.h>
# include <stdlib.h>
//创建一个 Student 结构体
struct Student
{
char name[30];
float fScore[3];
};
struct Student su = {"testsdk",98.5,89.0,93.5};
void Display(struct Student su)
{
printf("-----Information------\n");
printf("Name:%s\n",su.name);
printf("Chinese:%.2f\n",su.fScore[0]);
printf("Math:%.2f\n",su.fScore[1]);
printf("English:%.2f\n",su.fScore[2]);
printf("平均分数为:%.2f\n",(su.fScore[0]+su.fScore[1],su.fScore[2])/3);
}
int main ()
{
Display(su);
return 0;
}
输出(这是我想用 python 调用的期望结果)
-----Information------
Name:testsdk
Chinese:98.50
Math:89.00
English:93.50
平均分数为:31.17
[Finished in 0.3s]
但我用 python 调用的时候,传递的结构体识别不了,都是空的,应该是没识别是结构体
-----Information------
Name:
Chinese:0.00
Math:0.00
English:0.00
平均分数为:0.00
----- finish -----
求各位指教,谢谢大家
1
wwqgtxx 2018-03-17 16:09:11 +08:00 via iPhone
问题在于 byref 实际上是传递了指针进去,而你需要的是直接传递结构体,而不是一个指向结构体的指针
|
3
wwqgtxx 2018-03-17 16:11:46 +08:00 via iPhone
你试试
lib.Display.argtypes = [Student] lib.Display(su) 这样能不能工作 |
4
wwqgtxx 2018-03-17 16:14:23 +08:00 via iPhone
另外,你的 Student 类定义的并不对,你也需要在 python 中为 name[30]保持同样的定义,而不是一个 c_char_p,应该是 c_char*30
|
5
pyse OP @wwqgtxx
厉害厉害。直中要害,用你这个办法,确实传递成功了!!!,太感谢了!!!!!! -----Information------ Name:test34954 Chinese:15.10 Math:13.20 English:51.30 平均分数为:17.10 ----- finish ----- |
6
pyse OP @wwqgtxx
我后来也发现了,改过来了。因为不懂 C,都是参照网上例子照猫画虎。。总之,万分感谢,我这个问题,搞了 2 天了,早知道就早些在 V2EX 求助了 |