首页 > 编程语言 >浅析 C++ 调用 Python 模块

浅析 C++ 调用 Python 模块

时间:2022-09-29 21:45:41浏览次数:87  
标签:调用 Python Py C++ PyObject 模块 浅析

浅析 C++ 调用 Python 模块

作为一种胶水语言,Python 能够很容易地调用 CC++ 等语言,也能够通过其他语言调用 Python 的模块。

Python 提供了 C++ 库,使得开发者能很方便地从 C++ 程序中调用 Python 模块。

具体的文档参考官方指南:
Embedding Python in Another Application

调用方法

1 链接到 Python 调用库

Python 安装目录下已经包含头文件( include 目录)和库文件 ( Windows 下为 python27.lib)。

使用之前需要链接到此库。

2 直接调用 Python 语句

#include "python/Python.h"

int main()
{
    Py_Initialize();    ## 初始化

    PyRun_SimpleString("print 'hello'");

    Py_Finalize();      ## 释放资源
}

3 加载 Python 模块并调用函数

~/test 目录下含有 test.py :

def test_add(a, b):
    print 'add ', a, ' and ', b
    return a+b

则可以通过以下代码调用 test_add 函数 :

#include "python/Python.h"
#include <iostream>
using namespace std;

int main()
{
    Py_Initialize();    // 初始化

    // 将Python工作路径切换到待调用模块所在目录,一定要保证路径名的正确性
    string path = "~/test";
    string chdir_cmd = string("sys.path.append(\"") + path + "\")";
    const char* cstr_cmd = chdir_cmd.c_str();
    PyRun_SimpleString("import sys");
    PyRun_SimpleString(cstr_cmd);

    // 加载模块
    PyObject* moduleName = PyString_FromString("test"); //模块名,不是文件名
    PyObject* pModule = PyImport_Import(moduleName);
    if (!pModule) // 加载模块失败
    {
        cout << "[ERROR] Python get module failed." << endl;
        return 0;
    }
    cout << "[INFO] Python get module succeed." << endl;

    // 加载函数
    PyObject* pv = PyObject_GetAttrString(pModule, "test_add");
    if (!pv || !PyCallable_Check(pv))  // 验证是否加载成功
    {
        cout << "[ERROR] Can't find funftion (test_add)" << endl;
        return 0;
    }
    cout << "[INFO] Get function (test_add) succeed." << endl;

    // 设置参数
    PyObject* args = PyTuple_New(2);   // 2个参数
    PyObject* arg1 = PyInt_FromLong(4);    // 参数一设为4
    PyObject* arg2 = PyInt_FromLong(3);    // 参数二设为3
    PyTuple_SetItem(args, 0, arg1);
    PyTuple_SetItem(args, 1, arg2);

    // 调用函数
    PyObject* pRet = PyObject_CallObject(pv, args);

    // 获取参数
    if (pRet)  // 验证是否调用成功
    {
        long result = PyInt_AsLong(pRet);
        cout << "result:" << result;
    }

    Py_Finalize();      ## 释放资源

    return 0;
}

参数传递

1 C++Python 传递参数

Python 的参数实际上是元组,因此传参实际上就是构造一个合适的元组。

常用的有两种方法:

  • 使用 PyTuple_New 创建元组, PyTuple_SetItem 设置元组值

    PyObject* args = PyTuple_New(3);
    PyObject* arg1 = Py_BuildValue("i", 100); // 整数参数
    PyObject* arg2 = Py_BuildValue("f", 3.14); // 浮点数参数
    PyObject* arg3 = Py_BuildValue("s", "hello"); // 字符串参数
    PyTuple_SetItem(args, 0, arg1);
    PyTuple_SetItem(args, 1, arg2);
    PyTuple_SetItem(args, 2, arg3);
    
  • 直接使用Py_BuildValue构造元组

    PyObject* args = Py_BuildValue("(ifs)", 100, 3.14, "hello");
    PyObject* args = Py_BuildValue("()"); // 无参函数
    

    i, s, f之类的格式字符串可以参考 格式字符串

2 转换 Python 返回值

调用 Python 得到的都是PyObject对象,因此需要使用 Python 提供的库里面的一些函数将返回值转换为 C++ , 例如 PyInt_AsLongPyFloat_AsDoublePyString_AsString 等。

还可以使用 PyArg_ParseTuple 函数来将返回值作为元组解析。

PyArg_Parse 也是一个使用很方便的转换函数。

PyArg_ParseTuplePyArg_Parse 都使用 格式字符串

注意事项

  1. 需要将 Python 的工作目录切换到模块所在路径
  2. 按照模块名加载而不是文件名
  3. 模块加载或者函数加载需要验证是否成功,否则可能会引起堆栈错误导致程序崩溃
  4. 需要使用 Py_DECREF(PyObject*) 来解除对象的引用(以便Python垃圾回收)

标签:调用,Python,Py,C++,PyObject,模块,浅析
From: https://www.cnblogs.com/mxnote/p/16743183.html

相关文章

  • C++ CMake 使用 Python3
    C++CMake使用Python3CMakeListst设置#如果使用的是非系统目录下的Python可以通过指定Python3_ROOT_DIR改变查找路径#set(Python3_ROOT_DIR"${CMAKE_SOURCE_D......
  • Python操作数据库
    python使用MySQL主要有两个模块,pymysql(MySQLdb)和SQLAchemy。pymysql(MySQLdb)为原生模块,直接执行sql语句,其中pymysql模块支持python2和python3,MySQLdb只支持python2,两者......
  • python实现找到列表中第二大的数字
    '''给定一个长度大于3的列表,里面数字是无序的,且数字不重复,如何找到第二大的数字?例如列表a=[1,3,6,2,7,9],找到的结果就应该是:7下面给出六种解决方案'''a=[1,3,6......
  • Python基础7
    今日内容概要数据类型内置方法理论整型相关操作浮点型相关操作字符串相关操作列表相关操作可变与不可变今日内容详细数据类型内置方法理论数据类型......
  • Python3安装psutil报错
    报错:pip3installpsutilcompilationterminated.error:command'gcc'failedwithexitstatus1解决:yuminstallpython3-devel继续安装:[root@centos......
  • 快手Python笔试题【杭州多测师】【杭州多测师_王sir】
    deftest():foriinrange(10):ifi%2!=0:print("helloworld")else:passtest()#调用函数packagecom.duoc......
  • 学习python-Day66
    今日学习内容前后端开发模式API接口postman使用序列化和反序列化restful规范drf:第三方app>>>快速实现符合restful规范的接口视图类,都是继承APIView......
  • python如何制作并安装自建包?
    一、依赖首先检查python是否安装了wheel、setuptools包,没有则使用pip安装pipinstallwheel--force-reinstallpipinstallsetuptools--force-reinstall 二、准......
  • C++ 调用python方法
    主流方法将python程序编程文本形式的动态链接库,在c/c++程序中调用其中定义的函数。本质上是在c++中启动了一个python解释器,由解释器对python相关的代码进行执行,执行......
  • Python基础
    1.为什么学习Python2.Python和其他语言的区别从三个方面看Python语言特点语言类型第三方库3.Python的优势4.Python的解释器种类?5.python2和python3区别6.深拷贝......