浅析 C++ 调用 Python 模块

作为一种胶水语言,Python 能够很容易地调用 C 、 C++ 等语言,也能够通过其他语言调用 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;
}

参数传递

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("()"); // 无参函数
  • isf之类的格式字符串可以参考 格式字符串

2 转换 Python 返回值

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

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

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

PyArg_ParseTuple 和 PyArg_Parse 都使用 格式字符串

注意事项

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

http://blog.csdn.net/tobacco5648/article/details/50890106

浅析 C++ 调用 Python 模块的更多相关文章

  1. 编程:C#调用Python模块

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

  2. 嵌入Python系列 | 调用Python模块中无参数函数

    开发环境 Python版本:3.6.4 (32-bit) 编辑器:Visual Studio Code C++环境:Visual Studio 2013 需求说明 在用VS2013编写的Win32程序 ...

  3. 嵌入Python | 调用Python模块中有参数的函数

    开发环境Python版本:3.6.4 (32-bit)编辑器:Visual Studio CodeC++环境:Visual Studio 2013 需求说明前一篇<在C++中嵌入Python|调 ...

  4. 嵌入Python | 调用Python模块中无参数的函数

    开发环境 Python版本:3.6.4 (32-bit) 编辑器:Visual Studio Code C++环境:Visual Studio 2013 需求说明 在用VS2013编写的Win32程序 ...

  5. c#项目调用Python模块的方法

    将Python模块用pyinstaller打包成exe程序 下载安装UPX((http://upx.sourceforge.net/)) ,并把路径加到环境变量中. UPX是开源的加壳和压缩exe的程 ...

  6. shell脚本调用python模块

    python helloworld.py代码为 # coding:utf-8 from __future__ import print_function import sys print(sys.pa ...

  7. R调用python模块

    明明已经安装了sctransfer,但仍然显示没有该模块 Error in py_module_import(module, convert = convert) : ModuleNotFoundEr ...

  8. [转] C/C++ 调用Python

    from :  https://cyendra.github.io/2018/07/10/pythoncpp/ 目录 前言 官方文档 环境搭建 编译链接 Demo 解释器 初始化 GIL Object ...

  9. linux下python调用c模块

    在C调用Python模块时需要初始化Python解释器,导入模块等,但Python调用C模块却比较简单,下面还是以helloWorld.c 和 main.py 做一说明:   (1)编写C代码,hel ...

随机推荐

  1. mysql 8 远程连接注意事项

    1.首先如果你是在windows平台下连接linux下的mysql 那么请确保linux下的防火墙开放3306端口 vi /etc/sysconfig/iptables在配置文件里增加一行 -A RH ...

  2. vim note (2)

    :e          edit :edit       edit :e.         edit current file '.'  a dot is means current : w writ ...

  3. navigator 页面链接

    页面链接. 属性名 类型 默认值 说明 url String   应用内的跳转链接 redirect Boolean false 是否关闭当前页面 hover-class String navigat ...

  4. 【33.00%】【vijos P1002】过河

    描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上 ...

  5. Java InputStream、String、File相互转化 --- good

    String --> InputStreamByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes()); Inp ...

  6. WPF 好看的矢量图标

    原文:WPF 好看的矢量图标 本文告诉大家一个好用的网站,里面提供很多好看的图标. 本文介绍的网站是 Xamalot 里面有很多好看的图标. 例如我找到了一个好看的图标 我只需要点击下面的下载就可以了 ...

  7. Win7使用初体验

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近装了个Win7旗舰版.随着年纪渐大,我对软件使用越来越趋于务实,不再追求最新版本,因为我评价一个好软件的标准是适用 ...

  8. C# WPF 一直保持多个Topmost窗体的置顶顺序

    原文:C# WPF 一直保持多个Topmost窗体的置顶顺序 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37862405/article/ ...

  9. WPF扑克牌之红桃K

    原文:WPF扑克牌之红桃K 有些什么用途呢?我想,如果你有兴趣,可用来制作WPF扑克牌游戏. 没有任何技术含量,需要做的是在Blend中绘图或者使用Illustrator,CoreDraw等矢图设计软 ...

  10. JPA示例项(J采纳PA的hibernate实现版本号)

    (1).JPA介绍: JPA全名Java Persistence API ,Java坚持API这是Sun公司Java EE 5规范中提出的Java持久化接口. JPA吸取了眼下Java持久化技术的长处 ...