0.引言
本地配置:
Windows10;
python3.7.6,64bit;
visual studio 2019;
最近写程序的时候一直是使用的C++,所有功能都需要手写代码来实现,不如Python方便,比如数据处理,再加上本身C++学的也很一般,于是师姐给我推了Python/C API的文档。Python/C API 因为老是会忘记以前干了啥,故在这里记录一下操作的过程。
1.VS环境配置
直接在VS里面引用Python.h
是会提醒找不到Python.h
的,用Everything
搜一下,在Python3x下的include目录下面。一开始查的有的博客里面说pip install python3-dev
,傻乎乎的弄了好久,没用不要信。把这个目录加到 C/C++ -> 常规 -> 附加包含目录
里面去。
然后是库python31_d.lib
,我电脑里面没有,按照这篇博客里面说的办法搞定了。
2.运行代码
这里参考的是这篇博客。先随便写个 hello world
程序,然后编译一下,在 Project/x64/Debug
目录下会生成.exe文件。
// main.cpp
#include <iostream>
#include "Python.h"
using namespace std;
int main(){
cout << "Hello World" << endl;
return 0;
}
然后在.exe
同目录下写一个python
程序,保存为"test_python.py"
#test_python.py
def Hello():
print("Hello")
def Add(a,b):
return a+b
然后修改main.cpp
:
/*********************************************************************************************
@ Author : ${ lwk }
@ Software : ${ Microsoft Visual Studio 2019 }
@ Windows SDK: ${ 10.0 }
@ Filename : ${ main }.cpp
@ Creat Time : ${ 2020/8/19 } ${ 16:01 }
@ Last Edit : ${ 2020/8/19 } ${ 18:02 }
**********************************************************************************************/
#include <iostream>
#include "Python.h"
using namespace std;
int main()
{
Py_Initialize(); //初始化,创建一个Python虚拟环境
if (Py_IsInitialized())
{
PyObject* pModule = NULL;
PyObject* pFunc = NULL;
pModule = PyImport_ImportModule("test_python"); //参数为Python脚本的文件名
if (pModule)
{
pFunc = PyObject_GetAttrString(pModule, "Add"); //获取函数
PyObject* pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2)); //0:表示序号。第一个参数。
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4)); //1:也表示序号。第二个参数。i:表示传入的参数类型是int类型。
PyObject* pReturn = PyEval_CallObject(pFunc, pArgs); //执行函数
int nResult;
PyArg_Parse(pReturn, "i", &nResult);
cout << nResult << endl;
}
else
{
printf("导入Python模块失败...\n");
}
}
else
{
printf("Python环境初始化失败...\n");
}
Py_Finalize();
}
直接运行,成功调用Add()
函数
查了点资料,记录一下Py_BuildValue
的参数,来源于这篇博客
"s" (string) [char *] :将C字符串转换成Python对象,如果C字符串为空,返回NONE。
"s#" (string) [char *, int] :将C字符串和它的长度转换成Python对象,如果C字符串为空指针,长度忽略,返回NONE。
"z" (string or None) [char *] :作用同"s"。
"z#" (string or None) [char *, int] :作用同"s#"。
"i" (integer) [int] :将一个C类型的int转换成Python int对象。
"b" (integer) [char] :作用同"i"。
"h" (integer) [short int] :作用同"i"。
"l" (integer) [long int] :将C类型的long转换成Pyhon中的int对象。
"c" (string of length 1) [char] :将C类型的char转换成长度为1的Python字符串对象。
"d" (float) [double] :将C类型的double转换成python中的浮点型对象。
"f" (float) [float] :作用同"d"。
"O&" (object) [converter, anything] :将任何数据类型通过转换函数转换成Python对象,这些数据作为转换函数的参数被调用并且返回一个新的Python对象,如果发生错误返回NULL。
"(items)" (tuple) [matching-items] :将一系列的C值转换成Python元组。
"[items]" (list) [matching-items] :将一系列的C值转换成Python列表。
"{items}" (dictionary) [matching-items] :将一系类的C值转换成Python的字典,每一对连续的C值将转换成一个键值对。
例如:
Py_BuildValue("") None
Py_BuildValue("i", 123) 123
Py_BuildValue("iii", 123, 456, 789) (123, 456, 789)
Py_BuildValue("s", "hello") 'hello'
Py_BuildValue("ss", "hello", "world") ('hello', 'world')
Py_BuildValue("s#", "hello", 4) 'hell'
Py_BuildValue("()") ()
Py_BuildValue("(i)", 123) (123,)
Py_BuildValue("(ii)", 123, 456) (123, 456)
Py_BuildValue("(i,i)", 123, 456) (123, 456)
Py_BuildValue("[i,i]", 123, 456) [123, 456] Py_BuildValue("{s:i,s:i}", "abc", 123, "def", 456) {'abc': 123, 'def': 456}
Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))