将Python嵌入C++

  |  

摘要: 将 Python 嵌入 C++ 的方法

【对数据分析、人工智能、金融科技、风控服务感兴趣的同学,欢迎关注我哈,阅读更多原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:潮汐朝夕
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings


在文章 Python与C的交互 中,我们知道 Python 与 C++ 交互有 Python 扩展、Python 嵌入、Python 调用这三类。

我们已经知道 Python 扩展的方法,例如 Cython、ctypes、SWIG 等,可以参考以下文章:

以上都是对 Python 进行扩展,用 C 函数库扩展 Python 的功能。反过来也是可以的,将 Python 嵌入到 C/C++ 中丰富其功能,本文我们入门一下 Python 嵌入的知识,并提供一个最简单的例子。更详细的内容参考这份文档:在其它应用程序嵌入 Python

Python 嵌入

初始化解释器

若要嵌入 Python,就要提供自己的主程序。此主程序要做的事情之一就是初始化 Python 解释器。至少得调用函数 Py_Initialize()。还有些可选的调用可向 Python 传递命令行参数。之后即可从应用程序的任何地方调用解释器了。

调用解释器

调用解释器的方式有好几种:

  • PyRun_SimpleString() 传入一个包含 Python 语句的字符串
  • PyRun_SimpleFile() 传入一个 stdio 文件指针和一个文件名(仅在错误信息中起到识别作用)。
  • 调用底层操作来构造并使用 Python 对象。

文档

Python/C API 参考手册 中介绍了希望编写扩展模块并将 Python 解释器嵌入其应用程序中的 C 和 C++ 程序员可用的 API。

扩展和嵌入 Python 解释器 中也描述了扩展编写的一般原则可以参考。


在 C++ 中嵌入 Python

将 Python 嵌入到 C++ 程序中去,实现方式将取决于 C++ 系统的实现细节;一般需用 C++ 编写主程序,并用 C++ 编译器来编译和链接程序。不需要用 C++ 重新编译 Python 本身。

这里我们看一个简单的例子,我们在 C++ 中调用一个 Python 代码,调用解释器的方法用的是 PyRun_SimpleFile(),Python 代码中使用了一些 pandas/numpy 中的功能。

C++ 主程序

hello.cpp 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <Python.h>
#include <stdio.h>

int main()
{
char filename[] = "test.py";
FILE *fp;

Py_Initialize();

fp = _Py_fopen(filename, "r");
PyRun_SimpleFile(fp, filename);

Py_Finalize();
return 0;
}

编译

编译命令如下:

1
g++ hello.cpp -include /root/anaconda3/include/python3.9/Python.h -L/root/anaconda3/lib -lpython3.9 -o hello

其中:

1
2
3
-I 后面跟的是(which python 对应路径的 include 位置)
-L 后面跟的是(which python 对应路径的 lib 位置)
-lpython3.9 对应的是 libpython3.9.so

Python 代码

1
2
3
4
5
6
7
8
9
import numpy as np
import pandas as pd

rng = pd.date_range("20210309", periods=6, freq="D")
print(rng)
print("===")
ts = pd.Series(np.random.rand(len(rng)), index=rng)
rng = pd.date_range("20210309", periods=6, freq="D", tz="UTC")
print(rng)

执行 ./hello,首先需要设置一下 LD_LIBRARY_PATH 环境变量:

1
export LD_LIBRARY_PATH=/root/anaconda3/lib:$LD_LIBRARY_PATH

结果如下:

1
2
3
4
5
6
7
8
DatetimeIndex(['2021-03-09', '2021-03-10', '2021-03-11', '2021-03-12',
'2021-03-13', '2021-03-14'],
dtype='datetime64[ns]', freq='D')
===
DatetimeIndex(['2021-03-09 00:00:00+00:00', '2021-03-10 00:00:00+00:00',
'2021-03-11 00:00:00+00:00', '2021-03-12 00:00:00+00:00',
'2021-03-13 00:00:00+00:00', '2021-03-14 00:00:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')

Share