使用Python调用C++库见:我的另一篇博客

工程配置

本文使用的项目构建工具为CMake,使用FindPython工具在CMake工程中找到Python库,注意CMake最低版本为3.12,参考:https://cmake.org/cmake/help/latest/module/FindPython.html

创建call_python.cpp文件,程序内容在下节详细说明。CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.12)
project(CallPython)find_package (Python COMPONENTS Interpreter Development)
message(STATUS "Python_VERSION: ${Python_INCLUDE_DIRS}")
include_directories(${PROJECT_SOURCE_DIR}/include${Python_INCLUDE_DIRS} )
# 生成目标文件
add_executable(call_python src/call_python.cpp)
# 链接库
target_link_libraries(call_python ${Python_LIBRARIES})

调用方法

使用C++调用Python脚本中的模块,一般需要经过如下几个步骤:

  1. 使用Py_Initialize()函数初始化Python解释器环境

  2. 添加.py脚本的路径,使用如下函数完成:

    // 添加.py的路径
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('脚本路径')");
    

    PyRun_SimpleString()函数也可以用来执行单条Python命令。

  3. 导入模块,使用PyImport_ImportModule('模块名')完成:

    PyObject* pModule = PyImport_ImportModule("模块名");
    
  4. 导入函数,使用PyObject_GetAttrString(模块指针, "函数名")来完成:

    PyObject* pFunc = PyObject_GetAttrString(pModule, "函数名");
    
  5. 构造函数的传入参数,要求以元组的形式传入,有两种方式进行构造,一种是使用Py_BuildValue()函数直接构造元组,使用方法如下:

    PyObject* args = Py_BuildValue("");
    

    其中()内可以指定参数格式,如下表所示:

    格式 实际输入
    Py_BuildValue("") None
    Py_BuildValue(“i”, 123) 123
    Py_BuildValue(“iii”, 123, 456, 789) 123, 456, 789
    Py_BuildValue(“f”, 123.456) 123.456
    Py_BuildValue(“fff”, 123.1, 456.2, 789.3) (123.1, 456.2, 789.3)
    Py_BuildValue(“s”, “hello”) ‘hello’
    Py_BuildValue(“(s)”, “hello”) (‘hello’,)
    Py_BuildValue(“ss”, “hello”, “world”) (‘hello’, ‘world’)
    Py_BuildValue("(i)", 123) (123,)
    Py_BuildValue("((ii)(ii)) (ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
    Py_BuildValue("{s:i,s:i}", “abc”, 123, “def”, 456) {‘abc’: 123, ‘def’: 456}

    注:实际输入中带()的格式才是元组形式,其余均不能直接作为参数传入到函数中。

    另一种方式是使用PyTuple_New(<length>)PyTuple_SetItem(参数指针, index, value)函数间接构造元组

    PyObject* args = PyTuple_New(2);
    PyTuple_SetItem(args, 0, Py_BuildValue("s", "python"));
    PyTuple_SetItem(args, 1, Py_BuildValue("i", 123);
    

    其中Py_BuildValue()使用方法见上表。

    如果传入参数是列表形式,则使用PyList_New()来构造一个列表,再将该列表加入到元组中即可

    // 构造一个列表,并添加成员
    PyObject* list = PyList_New(3);
    PyList_SetItem(list, 0, Py_BuildValue("i", 1));
    PyList_SetItem(list, 1, Py_BuildValue("i", 10));
    PyList_SetItem(list, 2, Py_BuildValue("i", 100));
    // 构造一个元组,将list加入到参数列表
    PyObject* args = PyTuple_New(1);
    PyTuple_SetItem(args, 0, list);
    
  6. 执行函数,使用PyObject_CallObject(函数指针, 参数指针)完成:

    PyObject_CallObject(pFunc, args);
    

    如果有返回值,则使用如下程序获取返回值:

    PyObject* pRet = PyObject_CallObject(pFunc, args);
    if (pRet)
    {long result = PyLong_AsLong(pRet); // 将返回值转换成long型  std::cout << "result:" << result << std::endl ;
    }
    
  7. 结束Python解释器:

    Py_Finalize();
    

举例

创建一个.py文件,命名为calculator.py,内容如下:

def add(a, b):print(a + b)return a + bdef helloworld(s):print("hello " + s)

现在我们要调用该脚本中的add函数和helloworld函数,C++程序如下:

#include <iostream>
#include <Python.h>int main(int argc, char** argv){// 运行Python解释器Py_Initialize();// 添加.py的路径PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('<scripts_path>')");/*********************************** add函数 ************************************/// 导入模块PyObject* pModule = PyImport_ImportModule("calculator");// 导入要运行的函数PyObject* pFunc = PyObject_GetAttrString(pModule, "add");// 构造传入参数    PyObject* args = PyTuple_New(2);PyTuple_SetItem(args, 0, Py_BuildValue("i", 1));PyTuple_SetItem(args, 1, Py_BuildValue("i", 10));// 运行函数,并获取返回值PyObject* pRet = PyObject_CallObject(pFunc, args);if (pRet){long result = PyLong_AsLong(pRet); // 将返回值转换成long型  std::cout << "result:" << result << std::endl ;}/******************************** helloworld函数 *******************************/// 导入函数pFunc = PyObject_GetAttrString(pModule, "helloworld");// 构造传入参数PyObject* str = Py_BuildValue("(s)", "python");// 执行函数PyObject_CallObject(pFunc, str);    // 终止Python解释器Py_Finalize();  }

运行结果:

11
result:11
hello python

使用C++调用Python模块(Linux)相关推荐

  1. C#调用Python模块

    编程:C#调用Python模块 当下,C#与Python都是比较热门的计算机编程语言,他们各有优缺点,如果能让他们互相配合工作,那是多么美好的事情,今天我来讲解一下如何利用C#来调用Python. 如 ...

  2. java执行python返回null_[转]java调用python脚本以及通过Process.waitFor()直接调用python模块返回错误代码1的一种解决办法...

    常见的java调用python脚本方式 通过jython提供的类库实现 通过Runtime.getRuntime()开启进程来执行脚本文件 通过jython提供的类库实现 通过jython实现的话,我 ...

  3. linux 下C调用Python 模块

    2019独角兽企业重金招聘Python工程师标准>>> 最近做一个移植项目, 用到C调用Python, 在网上搜了好多资料,但是发现按照上面介绍的一步一步来, 根本行不通,最后还是根 ...

  4. teststand调用python模块_NI TestStand 2019下载-测试管理软件NI TestStand 2019下载v19.0.1 官方版-西西软件下载...

    NI TestStand 2019是NI打造的一款可立即执行的测试管理软件,这款软件主要可以帮助测试和验证工程师快速构建和部署自动化测试系统.借助TestStand,您可以开发.执行和部署测试系统软件 ...

  5. android调用python模块 chaquo_小猿圈python学习-系统调用os模块

    os 模块提供了很多允许你的程序与操作系统直接交互的功能 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd()返回指定目录下的所有文件和目录名:os.listdir()函数 ...

  6. teststand调用python模块_TestStand 基本知识[10]--在序列中调用代码模块之--LabVIEW

    在TestStand调用外部代码模块时,使用频率最高的就是LabVIEW VI. 下面调用TestStand Demo程序,可以看到如下图: 1. 添加LabVIEW Action步骤,并创建或者加载 ...

  7. linux下调用python脚本,Linux下QT调用Python脚本的解决方案,Qt,python,一种,解决办法

    最近在做一个深度学习对图片中对象识别效果的检测工具,其主要功能就是将自己标注的图片与识别结果图片进行对比然后计算识别的准确等参数,并提供原图与结果图片的显示功能. 脚本主要完成识别与计算功能,QT完成 ...

  8. linux调用python出错,linux里面python调用系统命令问题

    想用linux里的awk处理一个文本,输入行号,打印出来.因为数据是逗号分隔的csv文件,我第一时间就想起了awk.但是在写python时,出错了. 以下是用shell写的程序可以运行: #!/bin ...

  9. linux下c 调用python,在Linux下使用python ctypes调用io\u submit

    我正在尝试使用python ctypes调用io帴ubmit. 我写的代码应该可以在32位和64位Intel/AMD体系结构上工作,但这里我将重点放在64位上.在 我定义了以下内容:def PADDE ...

最新文章

  1. 每日一皮:在同一个项目上工作2年的样子...
  2. keynotes egestas,PPT 渐变背景下载-imsoft.cnblogs
  3. http协议的缺点和确保web安全的https协议
  4. 【Linux】一步一步学Linux——ifup命令(152)
  5. wxwidget编译安装_wxWidgets的安装编译、相关配置、问题分析处理
  6. 技术文档的撰写_如何撰写出色的技术博客文章
  7. 格式化数字字符串输出的一个小技巧
  8. 萤火虫算法matlab实现,萤火虫算法,matlab代码.doc
  9. 《现代操作系统教程》课程课后习题及答案
  10. Ember controller
  11. GNSS/INS组合导航(九):三维简化的INS/GPS组合导航系统
  12. c语言手写平衡二叉树非递归实现
  13. oracle中取月初和月末的方法
  14. 浅析NDI 5(一)基于NDI 5如何打造全球NDI演播室?
  15. 16 服务器无响应什么意思,dns电脑服务器未响应是什么意思如何处理
  16. MySQL修改数据库名字
  17. Python数据分析——数据基础
  18. Java猿社区—Redis一篇系列—第一章、NoSql入门和概述
  19. 360随身wifi与wifi共享精灵PK之安全问题
  20. POSIX 线程具体解释(3-相互排斥量:固定加锁层次/“试加锁-回退”)

热门文章

  1. c语言比Java运算符不同,C语言运算符
  2. java c语言语法对比_c语言和java语法有区分吗?_后端开发
  3. 点云数据格式PCD(Point Cloud Data) 数据格式解析
  4. MySQL主从延迟的解决方案
  5. 代码怎样review?
  6. 字节、字、bit、byte的关系
  7. uart串口的verilog实现
  8. python 基于selenium的IP摄像头 网页按键PTZ控制 (2) 登录-松下摄像头的弹框登录方式
  9. BUAA OO 第二单元 电梯
  10. java.sql.SQLException错误