C++调用Python的方法

本文介绍了如何在C++程序中调用Python代码,包括初始化Python解释器、执行Python脚本、调用无参和有参Python函数。通过示例代码展示了如何传递参数并获取返回值,从而实现C++与Python的交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0 背景

在一个C/C++应用程序中,我们可以用一组插件来实现一些具有统一接口的功能,一般插件都是使用动态链接库实现,如果插件的变化比较频繁,我们可以使用 Python 来代替动态链接库形式的插件,这样可以很方便地更具需要求的变化改写脚本代码(进行不同的数据处理),而不是必须重新编译链接二进制的动态链接库。

在《Python调用C++程序的几种方法》中,我们介绍了 python 调用 c++ 的一些方法,实际项目中,有时会遇到 c++ 调用 python 的需求,比如实现代码加密、扩展 c++ 功能等功能,因此本文对相关方法做一个整理记录。

1 调用流程

c++ 调用 python ,本质上是在 c++ 中启动了一个 python 解释器,由解释器对 python 相关的代码进行执行,执行完毕后释放资源,达到调用目的。

下边的代码 main.cpp 包含了调用流程内容

// main.cpp
#include <Python.h>
int main(int argc, char *argv[]) {
  // 初始化python解释器.C/C++中调用Python之前必须先初始化解释器
  Py_Initialize();
  
  // 执行一个简单的执行python脚本命令
  PyRun_SimpleString("print('hello world')\n");

  // 撤销Py_Initialize()和随后使用Python/C API函数进行的所有初始化
  Py_Finalize();
  return 0;
}

编译方法(注意这里要替换为你实际使用的 python 库和头文件路径,可以使用 whereis python 指令找到)

g++ main.cpp  -I/usr/include/python3.5 -lpython3.5m -o test

运行后输出如下

2 无参函数调用

在上边的例子中,我们介绍了在 c++ 中执行 python 语句的方法,简单的完成了一个 print 功能。而实际使用时,我们需要调用 python 模块以及模块中的函数,并且有可能需要参数传递以及返回值获取。我们首先先实现一个简单的无参数传递的函数调用功能。

#include <Python.h>
#include <iostream>

using namespace std;

int main(){
    // 1、初始化python接口  
	Py_Initialize();
	if(!Py_IsInitialized()){
		cout << "python init fail" << endl;
		return 0;
	}
    // 2、初始化python系统文件路径,保证可以访问到 .py文件
	PyRun_SimpleString("import sys");
	PyRun_SimpleString("sys.path.append('./script')");

    // 3、调用python文件名,不用写后缀
	PyObject* pModule = PyImport_ImportModule("sayhello");
	if( pModule == NULL ){
		cout <<"module not found" << endl;
		return 1;
	}
    // 4、调用函数
	PyObject* pFunc = PyObject_GetAttrString(pModule, "say");
	if( !pFunc || !PyCallable_Check(pFunc)){
		cout <<"not found function add_num" << endl;
		return 0;
	}
    // 
    PyObject_CallObject(pFunc, NULL);
    // 5、结束python接口初始化
	Py_Finalize();
	return 0;
}

 python 脚本内容

def say():
    print("hello")

编译并执行

3 有参函数调用

// test2.cpp
#include<Python.h> 
#include <iostream>
using namespace std;
 
int main()
{
    Py_Initialize(); //1、初始化python接口
    
    //初始化使用的变量
    PyObject* pModule = NULL;
    PyObject* pFunc = NULL;
    PyObject* pName = NULL;
    
    //2、初始化python系统文件路径,保证可以访问到 .py文件
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");
    
    //3、调用python文件名。当前的测试python文件名是 myadd.py
    // 在使用这个函数的时候,只需要写文件的名称就可以了。不用写后缀。
    pModule = PyImport_ImportModule("myadd");
    
    //4、调用函数
    pFunc = PyObject_GetAttrString(pModule, "AdditionFc");
    
    //5、给python传参数
    // 函数调用的参数传递均是以元组的形式打包的,2表示参数个数
    // 如果AdditionFc中只有一个参数时,写1就可以了
    PyObject* pArgs = PyTuple_New(2);

    // 0:第一个参数,传入 int 类型的值 2
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2)); 
    // 1:第二个参数,传入 int 类型的值 4
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4)); 
    
    // 6、使用C++的python接口调用该函数
    PyObject* pReturn = PyEval_CallObject(pFunc, pArgs);
    
    // 7、接收python计算好的返回值
    int nResult;
    // i表示转换成int型变量。
    // 在这里,最需要注意的是:PyArg_Parse的最后一个参数,必须加上“&”符号
    PyArg_Parse(pReturn, "i", &nResult);
    cout << "return result is " << nResult << endl;
    
    //8、结束python接口初始化
    Py_Finalize();
}

其中 python 脚本内容如下

# myadd.py
def AdditionFc(a, b):
    print("Now is in python module")
    print("{} + {} = {}".format(a, b, a+b))
    return a + b

编译并测试如下

在 Qt C++调用 Python方法,可以使用 Python 的 C/C++ API 或者使用第三方库,如 Boost.Python 或 pybind11。这里提供使用 Python C/C++ API 的方法。 首先需要在 Qt C++ 项目中添加 Python 的头文件和库文件路径。在 .pro 文件中添加以下代码: ```pro INCLUDEPATH += /usr/include/python3.6m/ LIBS += -L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu/ -lpython3.6m ``` 其中 `/usr/include/python3.6m/` 和 `/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu/` 是 Python 的头文件和库文件路径,需要根据实际情况进行修改。 然后在 Qt C++调用 Python方法,可以按照以下步骤进行: 1. 初始化 Python 解释器: ```c++ Py_Initialize(); ``` 2. 导入 Python 模块: ```c++ PyObject* pModule = PyImport_ImportModule("module_name"); ``` 其中 `"module_name"` 是 Python 模块的名称。 3. 获取 Python 方法: ```c++ PyObject* pFunc = PyObject_GetAttrString(pModule, "function_name"); ``` 其中 `"function_name"` 是 Python 方法的名称。 4. 调用 Python 方法: ```c++ PyObject* pArgs = PyTuple_New(1); PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", "argument")); PyObject* pResult = PyObject_CallObject(pFunc, pArgs); ``` 其中 `"argument"` 是传递给 Python 方法的参数。需要注意的是,在 Py_BuildValue 函数中需要指定参数类型,例如使用 `"s"` 表示字符串类型。 5. 处理 Python 方法的返回值: ```c++ char* result; PyArg_Parse(pResult, "s", &result); ``` 其中 `"s"` 表示返回值的类型为字符串类型。 6. 释放 Python 对象: ```c++ Py_DECREF(pArgs); Py_DECREF(pResult); Py_DECREF(pModule); ``` 最后,在程序结束时需要清理 Python 解释器: ```c++ Py_Finalize(); ``` 以上是基础的调用 Python 方法的步骤,具体实现还需要根据实际情况进行调整。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宗而研之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值