注:我使用的环境:IDLE (Python 3.6 32-bit) ;vs2010
以下环境配置部分详见:混合编程之——C++调用python2.7&python3.5
以python3.6为例:
需要单独将Python36-32下面的,include文件夹里面的头文件和libs文件夹里面的库函数都单独拷贝出来,至于怎么设置,怎么放,咱们慢慢来。
1、新建一个文件夹,取名为test_python36;
2、将Python36-32下面的,include文件夹、libs文件夹都拷贝到test_python36文件夹中,并把libs文件夹中的python36.lib拷贝一份并命名为python36_d.lib放在该文件下(libs下);
3、打开VS2010,新建一个项目(C_python),选好路径,文件夹test_python36里面的内容如下:
4、接下来需要配置项目(C_python)的环境变量
右键项目-》属性
(1)添加头文件
(2)添加库文件
5、生成解决方案,不会报错,但肯定没有结果,因为还没有添加动态链接库文件调用的python原函数。具体做法:在生成的Debug路径下添加调用的python原函数(例如:Test001.py),如下图所示
6、在运行程序过程中遇到的报错和解决办法:
(1)Cannot find or open the PDB file问题的解决
详见:http://blog.chinaunix.net/uid-11765716-id-3074932.html
(2)无法解析的外部符号 __imp__py_reftotal(或其他)
详见:https://www.jb51.net/article/108588.htm
1)初始化Python调用环境
2)加载对应的Python模块
3)加载对应的Python函数
4)将参数转化为Python元组类型
5)调用Python函数并传入参数元组
6)获取返回值
7)根据Python函数的定义解析返回值
注:在C中使用到的部分参数类型参照:详见:https://docs.python.org/3.6/c-api/arg.html
C部分:
//调用Add函数,传两个int型参数
void Add(){
int x=6,y=8;
Py_Initialize();
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
PyObject *pReturn = NULL;
//加载python模块
pModule = PyImport_ImportModule("Test001");//Test001:Python文件名
//加载对应的Python函数
pFunc = PyObject_GetAttrString(pModule, "Add");//Add:Python文件中的函数名
//创建参数:
PyObject *pArgs = PyTuple_New(2);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", x));//0--序号,i表示创建int型变量
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", y));//1--序号
//返回值
pReturn = PyEval_CallObject(pFunc, pArgs);//调用函数
//将返回值转换为int类型
int result;
PyArg_Parse(pReturn, "i", &result);//i表示转换成int型变量
printf("返回的结果result:%d + %d + 3= %d\n",x,y,result);
//cout << "6 + 8 = " << result << endl;
Py_Finalize();
}
Python部分:
def Add(a, b):
print(a,' + ',b,'=',a+b)
return a+b+3
C部分:
void Hello(){
Py_Initialize();//调用Py_Initialize()进行初始化
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
PyObject *pReturn = NULL;
pModule = PyImport_ImportModule("Test001");//调用的Python文件名
pFunc = PyObject_GetAttrString(pModule, "Hello");//调用的函数名
//创建参数:
PyObject *pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", "Hello Python!!"));
pReturn=PyEval_CallObject(pFunc, pArgs);//调用函数,并传入参数pArgs
char * result;
PyArg_Parse(pReturn, "s", &result);
printf("返回值:%s\n",result);
Py_Finalize();//调用Py_Finalize,和Py_Initialize相对应的.
}
Python部分:
def Hello(s):
print(s)
return "Hello C!!"
C部分:
void szTest(){
/*Pass by List: Transform an C Array to Python List*/
double CArray[] = {1.2, 4.5, 6.7, 8.9, 1.5, 0.5};
Py_Initialize();
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
PyObject *pDict = NULL;
PyObject *pReturn = NULL;
pModule = PyImport_ImportModule("Test001");
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, "szTest");
cout<<"C Array Pass Into The Python List:"<
Python部分:
def szTest(List):
print (List)
IntegerList = [1, 2, 3]
return IntegerList
list object(介绍C调用Python中,关于list的一些函数)
C部分:
void szSecTest(){
long CArray[2][3]={{2,3,4},{5,6,7}};
Py_Initialize();
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
PyObject *pDict = NULL;
PyObject *pReturn = NULL;
pModule = PyImport_ImportModule("Test001");
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict, "szSecTest");
cout<<"C two-dim Array Pass Into The Python List:"<
Python部分:
def szSecTest(List):
print (List)
IntegerList = [[1, 2, 3],[2,3,4]]
return IntegerList
1)Python:struct模块的pack、unpack
简单举一个例子如下:
print('===== pack - unpack =====' )
buf1 = 2
buf2 = 3
buf4 = 4
retResult = struct.pack('ii4si', buf1, buf2, b'abd', buf4)
print(type(retResult)) #
a1,a2,a3,a4=struct.unpack("ii4si",retResult)
print(a1,a2,bytes.decode(a3),a4)
2)Python中str与bytes的互相转换
a = "asdf"
b = a.encode('utf-8')#str转化为bytes
c = bytes.decode(b)#bytes转化为str
print(a,type(a),b,type(b),c,type(c))
结果图:
3)以下部分为C调用Python,传递结构体的代码部分
C部分:
typedef struct header_ {
int buf1;
int buf2;
char buf3[12];
int buf4;
}header;
void testStruct(){
// 初始化Python
Py_Initialize();
//PyObject *pName = PyBytes_FromString("Test001");PyObject *pModule = PyImport_Import(pName); //调用Python的Module的另一种方法
PyObject * pModule = NULL;
PyObject *pDict = NULL;
PyObject * pFunc = NULL;
pModule = PyImport_ImportModule("Test001");
if (!pModule) {
printf("can't find Test001.py");
return ;
}
pDict = PyModule_GetDict(pModule);
if (!pDict) return ;
//下面这段是查找函数testStruct并执行testStruct
pFunc = PyDict_GetItemString(pDict, "testStruct");
if (!pFunc || !PyCallable_Check(pFunc)) {
printf("can't find function [testStruct]");
return ;
}
//创建结构体
header input;
memset(&input,0,sizeof(input));
input.buf1 = 1;
input.buf2 = 2;
input.buf4 = 3;
strcpy_s(input.buf3, "kjaf");
//打包成string
char * byInput = new char(sizeof(input));
memcpy(byInput, &input, sizeof(input));
//申请python入参
PyObject *pArgs = PyTuple_New(1);
//对python入参进行赋值; s代表char*格式, #代表传入指定长度
PyTuple_SetItem(pArgs, 0, Py_BuildValue("s#",byInput , sizeof(input)));
//PyObject *Pystructs = Py_BuildValue("s#",byInput, sizeof(input));//为了检验入参是否为空
//if (Pystructs == nullptr){printf("Pystructs is nullptr"); }
//执行函数
PyObject *pResult = PyObject_CallObject(pFunc, pArgs);
char* pRsp;
//获取返回值
PyArg_Parse(pResult, "s#", &pRsp); //由于传回的参数为bytes(经过Python的unpack后,传回的参数),故用"s#",而不是"s"
//转成结构体
header* pstRsp = (header*)pRsp;//把string转化为结构体
printf("\n-----------c++层接收py返回:\nbuf1:%d , buf2:%d , buf3:%s , buf4:%d\n\n",
pstRsp->buf1, pstRsp->buf2, pstRsp->buf3, pstRsp->buf4);
Py_Finalize();
}
Python部分:
import struct
def testStruct(a):
a = a.encode('utf-8')#要注意把从C传过来的string转化为bytes,以便struct.unpack解析
ret = struct.unpack('i i 12s i', a)
print("--------------------python receive c++ struct:\n")
print(ret)
buf1 = ret[0] + 1
#print('buf1: ',buf1)
buf2 = ret[1] + 1
buf4 = ret[3] + 1
print("--------------------begin pack data and begin send to c++\n")
bin_buf_all = struct.pack('ii12si', buf1, buf2,b"dfds", buf4) #struct.pack后,bin_buf_all为bytes类型
print("----------------------------python end-----------------------")
return bin_buf_all
运行结果:
注:结构体显然就是一种的数据组织方式,使用结构体要注意数据对齐的问题,有兴趣的话可以看一下:https://blog.csdn.net/mirale/article/details/38128709
参考博文:
混合编程之——C++调用python2.7&python3.5
C++调用Python的API总结
C与python的调用一(导入python模块与,获得函数与类)
Python + C/C++ 嵌入式编程(1):多维数组Numpy.Array()在Python和C/C++文件间的传递问题
c++调用python系列(1): 结构体作为入参及返回结构体
python str与bytes转换
C中结构体和字节流的互换及内存对齐