当前位置:   article > 正文

C++使用Python/C API_python c++ api

python c++ api

目录

配置环境

第一步 导入Python3路径

第二步 测试环境

 运行例程

1. 直接运行Python代码段

2. 运行Python脚本

3. 导入Python模块,调用Python函数

4. 调用Python类

参考资料


配置环境

环境:Windows10、Visual Studio 2019、Python3.x

打开VS,建立空项目。

第一步 导入Python3路径

1. 项目→属性→C/C++→常规→附加包含目录,添加Python3安装路径\include

该文件夹下有Python.h,这就是C++调用Python的API前一定要include的库。

 2.  项目→属性→VC++目录→库目录,添加Python3安装路径\libs

 3. 项目→属性→链接器→输入→附加依赖项,添加Python3安装路径\libs\python39.lib。(如果Python版本是3.7则可以写python37.lib,以此类推)

4. 检查版本: 检查一下自己下载的Python是x86还是x64版本的,如果与VS版本不一致,可以在VS窗口上方调整项目版本。

第二步 测试环境

这是一个简单的helloworld程序。如果能够成功运行,则可以直接进入下一节。

  1. #include <Python.h>
  2. int main(int argc, char* argv[])
  3. {
  4. Py_Initialize();
  5. PyRun_SimpleString("print('Hello, world!')");
  6. Py_Finalize();
  7. return 0;
  8. }

 运行结果:

如果出现错误:LINK : fatal error LNK1104: 无法打开文件“python39_d.lib”,则说明没有安装Python的Debug功能,需要为Python增加Debug功能。增加方法如下图:

(注:针对该错误,除了本文中提到的方法,网上还有其它办法可供选择:扩展Python模块系列(一)----开发环境配置 - 建木 - 博客园 (cnblogs.com)。)

 运行例程

C++调用Python的结构都如下:

  1. #include <Python.h>
  2. int main(int argc, char* argv[])
  3. {
  4. Py_Initialize(); //初始化
  5. //... ...
  6. Py_Finalize(); //结束,释放资源
  7. return 0;
  8. }

注:下文仅包含C++运行或调用Python代码段、脚本、函数、类的基本方法,不包含进阶用法。

考虑到便利性,也由于其在 Python 解释器中被广泛使用, "Python.h" 还包含了一些标准头文件: <stdio.h> , <string.h> , <errno.h> 和 <stdlib.h> 。 如果后面的头文件在你的系统上不存在,它还会直接声明函数 malloc () , free () 和 realloc () 。

——Python官方文档

1. 直接运行Python代码段

  1. #include <Python.h>
  2. int main(int argc, char* argv[])
  3. {
  4. Py_Initialize();
  5. PyRun_SimpleString("print('Hello from Python string')");
  6. Py_Finalize();
  7. return 0;
  8. }

2. 运行Python脚本

源目录下helloScript.py:

print("Hello from Python script")

C++:

  1. //my_python.c
  2. #include <Python.h>
  3. int main(int argc, char* argv[])
  4. {
  5. Py_Initialize();
  6. PyObject* obj = Py_BuildValue("s", "helloScript.py");
  7. FILE* file = _Py_fopen_obj(obj, "r+");
  8. if (file != NULL)
  9. {
  10. PyRun_SimpleFile(file, "helloScript.py");
  11. }
  12. Py_Finalize();
  13. return 0;
  14. }

3. 导入Python模块,调用Python函数

源目录下hello.py:

  1. def Hello():
  2. print("Hello from Python module")
  3. def Add(a, b):
  4. print ("Add function: ", end="")
  5. print (str(a) + " + " + str(b) + " = " + str(a+b))
  6. return a + b

C++:

  1. #include <Python.h>
  2. int main(int argc, char* argv[])
  3. {
  4. Py_Initialize();
  5. //必须修改Python路径,否则会找不到Python模块
  6. PyRun_SimpleString("import sys");
  7. PyRun_SimpleString("sys.path.append('./')");
  8. PyObject* pModule = NULL;
  9. PyObject* pFunc = NULL;
  10. //import模块
  11. pModule = PyImport_ImportModule("hello");//模块文件名
  12. //找不到模块则报错
  13. if (pModule == nullptr) {
  14. PyErr_Print();
  15. Py_Finalize();
  16. return 0;
  17. }
  18. //1. 调用不带参数的函数 Hello()
  19. pFunc = PyObject_GetAttrString(pModule, "Hello");//函数名
  20. PyObject_CallFunction(pFunc, NULL);//调用函数
  21. //2. 调用带参数的函数 Add(a, b)
  22. PyObject* pAdd = NULL;
  23. PyObject* args = NULL;
  24. pAdd = PyObject_GetAttrString(pModule, "Add");
  25. args = Py_BuildValue("(ii)", 123, 456); //设置传入Add的参数
  26. PyObject* pRet = PyObject_CallObject(pAdd, args); //pRet = Add(123, 456)
  27. //输出返回值
  28. int ans = 0;
  29. PyArg_Parse(pRet, "i", &ans);//返回类型转换
  30. printf("Return C++: ans = %d\n", ans);
  31. Py_Finalize();
  32. return 0;
  33. }

4. 调用Python类

注:调用类中方法的API不止一套,建议去官网看看,并且建议使用Python3.9版本以上才支持的API,那些API对类的支持更好,不容易出现需要手动加入Python类的self参数的问题。

源目录下helloClass.py:

  1. class myClass:
  2. welcome = "Hello from Python class attribute"
  3. def hello(self):
  4. print("Hello from Python class method")
  5. def minus(self, a, b):
  6. print(str(a) + " - " + str(b) + " = " + str(a-b))
  7. return a-b

C++:

(1)Python3.9以下可用:

  1. #include <Python.h>
  2. int main(int argc, char* argv[])
  3. {
  4. Py_Initialize();
  5. //必须修改Python路径,否则会找不到Python模块
  6. PyRun_SimpleString("import sys");
  7. PyRun_SimpleString("sys.path.append('./')");
  8. PyObject* pModule2 = NULL;
  9. PyObject* pFunc2 = NULL;
  10. PyObject* pClass = NULL;
  11. PyObject* pInstance = NULL;
  12. PyObject* args2 = NULL;
  13. pModule2 = PyImport_ImportModule("helloClass");//这里是要调用的文件名helloClass.py
  14. if (pModule2 == NULL)
  15. {
  16. PyErr_Print();
  17. Py_Finalize();
  18. return 0;
  19. }
  20. // 模块的字典列表
  21. PyObject* pDict = PyModule_GetDict(pModule2);
  22. if (!pDict) {
  23. PyErr_Print();
  24. Py_Finalize();
  25. return 0;
  26. }
  27. //从字典中获取myClass类
  28. PyObject* pClassCalc = PyDict_GetItemString(pDict, "myClass");
  29. if (!pClassCalc) {
  30. PyErr_Print();
  31. Py_Finalize();
  32. return 0;
  33. }
  34. //构造实例
  35. PyObject* pInstanceCalc = PyInstanceMethod_New(pClassCalc);
  36. if (!pInstanceCalc) {
  37. PyErr_Print();
  38. Py_Finalize();
  39. return 0;
  40. }
  41. //获取pInstanceCalc实例的属性,转换成字符串并输出
  42. PyObject* obj2 = PyObject_GetAttrString(pInstanceCalc, "welcome");
  43. PyObject* str = PyUnicode_AsEncodedString(obj2, "utf-8", "strict");
  44. char* result = PyBytes_AsString(str);
  45. printf("%s\n", result);
  46. //如果属性是int型,可用下面这句转换属性:
  47. //int qwq;
  48. //PyArg_Parse(obj2, "i", &qwq);
  49. //调用无参数Python方法,s和pInstanceCalc对应Python中的self
  50. PyObject_CallMethod(pClassCalc, "hello", "s", pInstanceCalc);
  51. //调用多参数Python方法,(s,i,i)和pInstanceCalc、12、22 分别对应Python方法中的 self、a、b
  52. pRet = PyObject_CallMethod(pClassCalc, "minus","(s,i,i)",pInstanceCalc, 12, 22);
  53. if (!pRet)
  54. {
  55. PyErr_Print();
  56. Py_Finalize();
  57. return 0;
  58. }
  59. int res = 0;
  60. PyArg_Parse(pRet, "i", &res);//转换返回类型
  61. printf("Return C++: ans = %d\n", res);
  62. Py_Finalize();
  63. return 0;
  64. }

(2)Python3.9以上可用:

 

  1. PyObject* getClass(const char* fileName, const char* className) {
  2. //必须修改Python路径,否则会找不到Python模块
  3. PyRun_SimpleString("import sys");
  4. PyRun_SimpleString("sys.path.append('./')");
  5. PyObject* pModule = NULL;
  6. PyObject* pClass = NULL;
  7. PyObject* pInstance = NULL;
  8. pModule = PyImport_ImportModule(fileName);
  9. if (pModule == NULL)
  10. {
  11. PyErr_Print();
  12. Py_Finalize();
  13. return NULL;
  14. //return 0;
  15. }
  16. // 模块的字典列表
  17. PyObject* pDict = PyModule_GetDict(pModule);
  18. if (!pDict) {
  19. PyErr_Print();
  20. Py_Finalize();
  21. return NULL;
  22. //return 0;
  23. }
  24. //从字典中获取myClass类
  25. pClass = PyDict_GetItemString(pDict, className);
  26. if (!pClass) {
  27. PyErr_Print();
  28. Py_Finalize();
  29. return NULL;
  30. //return 0;
  31. }
  32. //实例化
  33. pInstance = PyObject_CallObject(pClass, NULL);
  34. return pInstance;
  35. }
  36. int main(){
  37. Py_Initialize();
  38. PyObject* pInstance = getClass("sarsaScript", "RL");
  39. //调用多参数Python类方法
  40. //cjoose_action是方法名
  41. PyObject* pAction = PyUnicode_FromString("choose_action");
  42. std::string state = "state1";
  43. PyObject* pState = PyUnicode_FromString(state.c_str());
  44. //参数以NULL结尾
  45. PyObject* pRet = PyObject_CallMethodObjArgs(pInstance, pAction, pState, NULL);
  46. if (!pRet)
  47. {
  48. PyErr_Print();
  49. Py_Finalize();
  50. return -1;
  51. }
  52. int res = 0;
  53. PyArg_Parse(pRet, "i", &res);//转换返回类型为int
  54. //调用无参数Python类方法
  55. //qwq是方法名
  56. PyObject* pQWQ = PyUnicode_FromString("qwq");
  57. PyObject_CallMethodNoArgs(pInstance, pQWQ);
  58. Py_Finalize();
  59. return 0;
  60. }

把上面的四段代码整合到一起运行,控制台输出为:

参考资料

文档:

  1. 官方API文档The Very High Level Layer — Python 3.10.11 documentation
  2. API文档中文版本C++调用Python浅析_pyeval_callobject_magictong的博客-CSDN博客
  3. 官方使用教程1. 在其它应用程序嵌入 Python — Python 3.7.13 文档
  4. 官方API手册Python 中文文档 - Python/C API 参考手册 | Docs4dev

博客:

  1. 精炼:[Python]C用API与Python交互_cpython api_西北丰的博客-CSDN博客
  2. 初学:
    1. C++调用python脚本 - 知乎 (zhihu.com)
    2. [C++/Python] 如何在C++中使用一个Python类? (Use Python-defined class in C++) - Lancelod_Liu - 博客园 (cnblogs.com)
    3. c++调用python的代码、函数、类 - 简书 (jianshu.com)
  3. 细致:C语言扩展Python模块 - 随笔分类 - 建木 - 博客园 (cnblogs.com)
  4. 踩坑经验:这里要隆重的写一下C++调用python遇到的各种坑,搞了好久,终于成功了!_c++调用python initfsencoding: unable to load the fil_Darling100的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/401111
推荐阅读
相关标签
  

闽ICP备14008679号