c++调用python的动态库——解决部署的trick

1、前言

算法开发时,有些部署流程比较繁琐。且坑比较多。以下写一个小的demo。将python程序打包成so库。并用c++调用。我这里时基于vscode开发的。

2、python demo

2.1 依赖安装

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

‌这条命令中的-i选项用于指定pip使用的镜像源,https://pypi.tuna.tsinghua.edu.cn/simple是清华大学的PyPI镜像源地址,它可以提供更快的下载速度,特别是在国内网络环境下。

永久配置清华源的方法如下:

1)如果你希望每次使用pip时都默认使用清华源,可以通过修改pip的配置文件来实现。在Windows上,找到或创建pip.ini文件(通常位于C:\Users\<YourUsername>\pip\pip.ini),并添加以下内容:

[global]
index-url=https://pypi.tuna.tsinghua.edu.cn/simple

2)在macOS和Linux上,找到或创建pip.conf文件(通常位于\~/.pip/pip.conf),并添加相同的内容。

配置完成后,你就可以像平常一样使用pip安装Python包了,pip会自动从清华源下载包。但请记住,你实际上安装的是Python的包或库,而不是cpython本身。cpython是Python的底层实现,它随着Python的安装程序一起被安装在你的系统上。

如果你想要安装特定版本的Python,你需要从Python的官方网站下载相应版本的安装包进行安装,而不是通过pip命令。在安装过程中,你可以选择是否将Python添加到系统的PATH环境变量中,以便在命令行中方便地运行Python。

2.2 程序demo

1、首先编写需要执行的程序。

# hello.pyx
def hello():
    return "Hello from Python!"

将后者替换为.pyx

2、编译

接下来,编写一个setup.py脚本来编译Python代码为动态库。确保你已经安装了Cython(可以通过pip install cython来安装)。

# setup.py
from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("hello.pyx"),
)

执行bash脚本进行编译

python setup.py build_ext --inplace

执行后,会在当前目录下生成动态库。

3、c++程序调用

#include <Python.h>

int main(int argc, char *argv[]) {
    // 初始化Python解释器
    Py_Initialize();

    // 添加当前路径到python路径(非常重要,不然会找不到这个so模块)
    PyRun_SimpleString("import sys\nsys.path.append('.'))
    // 加载Cython编译的.so模块
    PyObject* pName = PyUnicode_DecodeFSDefault("hello");  // your_cython_module
    PyObject* pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != nullptr) {
        // 获取模块中的函数
        PyObject* pFunc = PyObject_GetAttrString(pModule, "hello"); // your_cython_function

        // 检查函数是否可调用
        if (pFunc && PyCallable_Check(pFunc)) {
            // 准备函数参数(这里假设函数不接受参数)
            PyObject* pArgs = PyTuple_Pack(0);

            // 调用函数
            PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);

            // 处理返回值(这里只是简单地打印出来)
            if (pValue != nullptr) {
                printf("Result of call: %s\n", PyUnicode_AsUTF8(pValue));
                Py_DECREF(pValue);
            } else {
                PyErr_Print();
                fprintf(stderr, "Function call failed\n");
            }

            Py_DECREF(pFunc);
        } else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function 'your_cython_function'\n");
        }

        Py_DECREF(pModule);
    } else {
        PyErr_Print();
        fprintf(stderr, "Failed to load 'your_cython_module'\n");
    }

    // 终止Python解释器
    Py_Finalize();
    return 0;
}

4、编译执行

要编译并执行一个包含Python C API调用的C++程序,你需要确保你的系统上安装了Python开发包(通常包括Python头文件和库)。编译过程通常分为两个步骤:首先是编译C++代码,然后是链接生成可执行文件。

下面是一个简化的编译和执行过程的示例,基于上面的代码片段。请注意,这个例子假设你使用的是g++编译器,并且Python的安装路径是标准的(/usr/include/pythonX.Y和/usr/lib/pythonX.Y,其中X.Y是Python的版本号)。如果你的Python安装在不同的位置,你可能需要调整编译器的包含目录和链接目录。

首先,确保你的C++代码保存为一个文件,比如main.cpp

然后,在终端中执行以下命令来编译代码:

g++ -o my_program main.cpp -I/usr/include/python3.X -lpython3.X

在这里,my_program是你想要生成的可执行文件的名称,main.cpp是你的C++源文件名,-I/usr/include/python3.X指定了Python头文件的搜索路径(替换X为你的Python次版本号,比如8对于Python 3.8),-lpython3.X指定了要链接的Python库(同样替换X为版本号)。

编译成功后,你可以通过以下命令来运行生成的可执行文件:

./my_program

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值