c++调用python函数进行传参计算和返回

前言:

接上一篇python调用c++动态链接库,环境是VS2022和vscode2023
在python中有许多好用的库,比如numpy,opencv,如果你想在c/c++中调用,你就需要进行混合编程。混合编程涉及到了传递参数,接受参数。不同语言的参数还需要使用一个公共的变量进行计算。

配置环境:

编译器:VS2022,vscode2023
python版本:python3.9.6
在这里插入图片描述
在这里插入图片描述

基础夯实:

在C++中调用Python库是一个强大的功能,它允许你结合两种语言的优势:C++的性能和效率,以及Python的丰富库和易用性。要实现这一点,你通常需要使用Python的C API,即Python.h头文件中定义的函数和宏。以下是一些基础知识,帮助你开始在C++中调用Python库。

1. 初始化Python解释器

在任何Python API调用之前,你必须首先初始化Python解释器。这通常通过调用Py_Initialize()函数来完成。在程序的最后,你应该调用Py_Finalize()来清理Python解释器。

#include <Python.h>

int main() {
    Py_Initialize();
    // 你的Python代码调用
    Py_Finalize();
    return 0;
}

2. 导入Python模块

要使用Python库中的函数,你首先需要导入相应的Python模块。这可以通过PyImport_Import()函数完成,它返回一个表示模块的PyObject指针。

PyObject* pModule = PyImport_Import(PyUnicode_FromString("module_name"));
if (!pModule) {
    // 处理错误
}

3. 获取函数对象

一旦导入了模块,你就可以从中获取函数对象了。使用PyObject_GetAttrString()函数,你可以通过函数名获取到函数对象。

PyObject* pFunc = PyObject_GetAttrString(pModule, "function_name");
if (!pFunc || !PyCallable_Check(pFunc)) {
    // 处理错误
}

4. 调用Python函数

要调用Python函数,你需要创建一个包含所有参数的元组,并使用PyObject_CallObject()函数。

PyObject* pArgs = PyTuple_New(arg_count); // arg_count是参数的数量
// 设置元组中的参数值
// 例如:PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", value));

PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
// 检查pValue是否为NULL来处理可能的错误

5. 处理返回值

Python函数的返回值也是一个PyObject指针。你可以根据返回值的类型使用相应的Python API函数来提取值。

if (pValue) {
    // 例如,如果返回值是一个整数,你可以使用PyLong_AsLong()
    long result = PyLong_AsLong(pValue);
    Py_DECREF(pValue); // 不要忘记释放pValue
}

6. 错误处理

在调用Python API时,错误处理是非常重要的。Python API函数通常会返回一个NULL指针来表示错误。你应该检查每个返回值,并在出现错误时适当地处理它。

if (!some_python_function()) {
    // 处理错误,例如使用PyErr_Print()打印错误信息
}

7. 资源管理

在使用Python API时,你会创建很多PyObject对象。为了避免内存泄漏,你应该在不再需要这些对象时调用Py_DECREF()来释放它们。

8. 编译和链接

要编译包含Python API调用的C++代码,你需要确保链接了Python库。这通常意味着在编译命令中添加-lpythonX.Y标志,其中X.Y是你使用的Python版本号。

9. 线程安全性

如果你在多线程环境中使用Python,你需要注意Python的全局解释器锁(GIL)。在调用任何Python API函数之前,你必须确保持有GIL。

10. 进一步学习

Python的C API是非常强大和灵活的,但也可能相当复杂。除了官方文档之外,还有很多教程和示例代码可以帮助你学习如何在C++中调用Python代码。

通过掌握这些基础知识,你就可以开始在C++项目中集成Python库了。随着经验的积累,你将能够更熟练地处理复杂的集成场景。

效果展示:

在这里插入图片描述

实现功能:

实现c++调用python函数,传递参数并进行返回值的接收的效果。

操作步骤(保姆级教程)

第一步打开VS2022

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// Project1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

int main()
{
    std::cout << "Hello World!\n";
    system("pause");
}

在这里插入图片描述

第二步配置项目python环境

配置的步骤大致分为两部:
1.VS的项目属性>>配置属性>>C/C++>>添加包含目录中
2.VS的项目属性>>配置属性>>链接器>>附件库目录
3.验证环境安装正确性:

1.添加头文件

1.VS的项目属性>>配置属性>>C/C++>>添加包含目录中
C:\Users\wangningning\AppData\Local\Programs\Python\Python39\include
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后不要忘记点击确定,确定之后又回到属性界面。相当于把如下文件添加进去:
在这里插入图片描述

2.添加库文件

VS的项目属性>>配置属性>>链接器>>附件库目录>>(参考路径)
C:\Users\wangningning\AppData\Local\Programs\Python\Python39\libs

在这里插入图片描述
在这里插入图片描述
点击确定之后点击应用。
在这里插入图片描述

3.验证配置正确性。

实验代码:

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

在这里插入图片描述

第三步写一个简单的python文件(写的位置易错,需要重点注意)

注意(易出现错误),尽量和我的操作一致。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将代码填写进去,文件名是fun.py

#fun.py
import numpy as np
def fun1(x,y):
    print("fun1 called with x=",x," and y=",y)
    return x+y

在这里插入图片描述
python环境中没有装numpy的去装一个,直接再vscode的命令行里面输入

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy

第四步再VS中添加c++调用python的代码:

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

// 使用标准命名空间  
using namespace std;

int main() {
    Py_Initialize(); // 初始化python解释器  
    if (!Py_IsInitialized()) {
        cerr << "Python interpreter initialization failed." << endl;
        return -1;
    }

    PyObject* pName, * pModule, * pFunc, * pArgs; // 定义python对象  

    pName = PyUnicode_FromString("fun"); // 模块名应该是fun,因为文件名是fun.py  
    pModule = PyImport_Import(pName); // 载入fun模块  
    if (!pModule) {
        cerr << "Can't find fun.py" << endl;
        Py_DECREF(pName);
        Py_Finalize();
        return -1;
    }

    // 获取函数对象  
    pFunc = PyObject_GetAttrString(pModule, "fun1"); // 要调用的函数是fun1  
    if (!pFunc || !PyCallable_Check(pFunc)) {
        cerr << "Cannot find function 'fun1'" << endl;
        Py_DECREF(pName);
        Py_DECREF(pModule);
        Py_Finalize();
        return -1;
    }

    // 准备调用fun1函数,它需要两个参数  
    pArgs = PyTuple_New(2); // 创建一个元组,长度为2  
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 5)); // 将第一个参数设置为整数5  
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 10)); // 将第二个参数设置为整数10  

    // 调用fun1函数  
    PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
    if (pValue != nullptr) {
        // 处理返回值(如果需要)  
        cout << "Function returned: " << PyLong_AsLong(pValue) << endl;
        Py_DECREF(pValue);
    }
    else {
        cerr << "Function call failed." << endl;
    }

    // 销毁python相关对象  
    Py_DECREF(pName);
    Py_DECREF(pModule);
    Py_DECREF(pArgs);
    Py_DECREF(pFunc);

    Py_Finalize();
    system("pause"); // 等待用户输入
    return 0;
}

在这里插入图片描述

我们发现c++成功调用了python的代码,对c++传递的参数进行计算,同时c++对于python返回的结果进行接收。本人也是在技术中学习,欢迎指正文章中的问题,共同进步。

参考资料:

https://zhuanlan.zhihu.com/p/146659551

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值