概述
python调用.c遇到的一些问题及解决方法(读取ATI六维力传感器测得数据)
- 前言
- 一、使用ctypes外部函数库
- 二、编译.c程序在python中调用
- 1.编译.c程序
- 2.python中调用
- 3.使用.c程序中的局部变量
- 总结
前言
工作需要读取六维力传感器测得的数据,现有一个ATI公司提供的.c的程序可以读取ait mini45的数据,因为想要在python里做数据的处理,把.c改成python也需要大量的时间精力,而且c执行的速度也要比python快不是一点半点,所以用到python调用c动态库。
一、使用ctypes外部函数库
from ctypes import *
ctypes官方文档
ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.
谷歌翻译:ctypes是Python的外部函数库。 它提供C兼容的数据类型,并允许在DLL或共享库中调用函数。 它可以用于将这些库包装在纯Python中。
二、编译.c程序在python中调用
1.编译.c程序
因为我是在linux环境下编译使用的,所以要编译成.so文件(Windows下需要编译为.dll文件)。
在命令行输入
gcc net.c -shared -o net.so
但我的电脑会报错
所以输入
gcc net.c -shared -o net.so -std=c99 -fPIC
编译成功
根据.c文件名称不同更改net.c。
2.python中调用
直接使用ctypes的方法LoadLibrary。
# python端代码
from ctypes import *
library = cdll.LoadLibrary("./net.so")
library.main()
//c 端代码
#inclue <stdio.h>
void main(){
print("*****************")
}
执行结果
至此已经成功调用c语言程序
3.使用.c程序中的局部变量
这里是我卡的最久的地方,因为我需要的数据在c里是一个数组,可以在执行c的时候printf打印出来,但是我不知道如何在python中使用这些数据。
需要的数据是六维力传感器六个维度的测量值:
虽然是用python执行打印出来的,但是这些是.c里的局部变量,执行完调用的c程序就没了。
一开始我尝试用return返回一个数组,python里面接收这个函数的返回值,但是怎么弄都只能接受int类型的返回值,也就只能返回数组里一个元素的值。后来把打算把这些数据转换为str字符串的类型,中间使用“ ”或者“|”分隔开,然后进行返回。
结果还是以失败告终。
不断的查找资料,结果不是讲的太浅(没怎么将数据类型之间的转换),就是讲的太深,实在是看不懂别人的程序(因为我比较菜)。
最后找到了这一篇,非常感谢作者
Python调用c/c++动态库(一)
看到这个地方,才真正解决了我的问题,虽然我写的还是很low,但终于可以把我需要的数据送到python程序里了。
下面是ATI提供的.c程序,我仅仅修改了主函数的输入值,以便输出给我python程序,最下面注释掉的部分是我尝试的过程。
/* Simple demo showing how to communicate with Net F/T using C language. */
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define PORT 49152 /* Port the Net F/T always uses 通常使用端口*/
#define COMMAND 2 /* Command code 2 starts streaming 命令代码2开始流*/
/* Typedefs used so integer sizes are more explicit 使用Typedefs使整数大小明确*/
typedef unsigned int uint32;
typedef int int32;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned char byte;
typedef struct response_struct {
uint32 rdt_sequence;
uint32 ft_sequence;
uint32 status;
int32 FTData[6];
} RESPONSE;
int main(int * a,int * b,int * c ,int * d,int * e,int * f) {
int socketHandle;
/* Handle to UDP socket used to communicate with Net F/T. 处理用于Net F/T通讯的UDP套接字*/
struct sockaddr_in addr; /* Address of Net F/T. Net F/T的ip地址*/
struct hostent* he;
/* Host entry for Net F/T. Net F/T的主机条目*/
byte request[8];
/* The request data sent to the Net F/T. 发送到Net F/T的请求数据*/
RESPONSE resp;
/* The structured response received from the Net F/T. 从Net F/T接受到的结构体*/
byte response[36];
/* The raw response data received from the Net F/T. 从Net F/T接受到的原始数据*/
int i;
/* Generic loop/array index. 通用 环/数组 索引*/
int err;
/* Error status of operations. 操作错误状态*/
char* AXES[] = { "Fx", "Fy", "Fz", "Tx", "Ty", "Tz" }; /* The names of the force and torque axes. */
/* Calculate number of samples, command code, and open socket here. 计算样本数 命令代码
打开socket*/
socketHandle = socket(AF_INET, SOCK_DGRAM, 0);
if (socketHandle == -1) {
exit(1);
}
*(uint16*)&request[0] = htons(0x1234); /* standard header. 标准头*/
*(uint16*)&request[2] = htons(COMMAND); /* per table 9.1 in Net F/T user manual. 根据用户手册表9.1*/
*(uint32*)&request[4] = htonl(1); /* see section 9.1 in Net F/T user manual. 用户手册9.1节*/
/* Sending the request. 发送请求*/
he = gethostbyname("192.168.1.1");
memcpy(&addr.sin_addr, he->h_addr_list[0], he->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
err = connect(socketHandle, (struct sockaddr*)&addr, sizeof(addr));
if (err == -1) {
exit(2);
}
send(socketHandle, request, 8, 0);
/* Receiving the response. 接受响应*/
recv(socketHandle, response, 36, 0);
resp.rdt_sequence = ntohl(*(uint32*)&response[0]);
resp.ft_sequence = ntohl(*(uint32*)&response[4]);
resp.status = ntohl(*(uint32*)&response[8]);
for (i = 0; i < 6; i++) {
resp.FTData[i] = ntohl(*(int32*)&response[12 + i * 4]);
}
/* Output the response data. 输出响应数据*/
int guo[6];
//printf("Status: 0x%08xn", resp.status);
for (i = 0; i < 6; i++) {
printf("%s: %dtn", AXES[i], resp.FTData[i]);
guo[i] = resp.FTData[i];
}
*a = guo[0];
*b = guo[1];
*c = guo[2];
*d = guo[3];
*e = guo[4];
*f = guo[5];
return 0;
// char str[50]={'