将 C++ 与 Python 连接

Posted

技术标签:

【中文标题】将 C++ 与 Python 连接【英文标题】:Interfacing C++ with Python 【发布时间】:2020-10-01 16:55:03 【问题描述】:

我有一个 c++ (C++ 17) library 和一个依赖于这个库的函数。我想从 python(python 3) 调用这个函数。怎么办?

我已经阅读了一些使用 swig 和 ctypes 的教程,但我不知道如何使它适用于外部共享库。

详情: 我在 /path/to/header/files 目录中有这个 libclickhouse-cpp-lib.so .so 文件和这个库的头文件。

/*File cpp_reader.h*/
#pragma once
int reader();
/* File cpp_reader.cpp*/
#include <clickhouse/client.h>
#include <iostream>
#include "cpp_reader.h"
using namespace clickhouse;
int reader()

    Client client(ClientOptions().SetHost("localhost"));
    int numrows=0;
    client.Select("SELECT count(*) from test.test_table",
        [&numrows] (const Block& block)
        
            for (size_t i=0;i<block.GetRowCount();++i)
            
                numrows+=block[0]->As<ColumnUInt64>()->At(i);
            
        
    );
    return(numrows);

我想从 python 调用这个读取函数。我已经使用 swig 和 ctypes 浏览了一些帖子,但无法弄清楚。如果使用其他任何东西都可以轻松完成,请也提出建议。

其他信息: 这就是我在 C++ 中运行代码的方式

/*File: main.cpp*/
#include <clickhouse/client.h>
#include <iostream>
#include <Python.h>
using namespace clickhouse;
int main()

    /// Initialize client connection.
    Client client(ClientOptions().SetHost("localhost"));
    int numrows=0;
    client.Select("SELECT count(*) from test.test_table",
        [&numrows] (const Block& block)
        
            for (size_t i=0;i<block.GetRowCount();++i)
            
                numrows+=block[0]->As<ColumnUInt64>()->At(i);
            
        
    );
    std::cout<<"Number of Rows: "<<numrows<<"\n";


编译:g++ -std=c++1z main.cpp -I/path/to/header/files -I/usr/include/python3.6m/ -L. /path/to/libclickhouse-cpp-lib.so -o outfile

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/so_file/directory导出 LD_LIBRARY_PATH

/path/to/so_file/directory 包含 libclickhouse-cpp-lib.so

./outfile

【问题讨论】:

pybind11 是我经验中最简单的方法。如果您已经在使用 Boost,boost.python 也不错。我不推荐ctypes,除非你只是在业余爱好项目上乱搞,我不推荐swig,除非你需要将你的C++暴露给Python之外的一堆其他语言。 我看不出cpp_reader.h#include &lt;clickhouse/client.h&gt; 甚至iostream 的理由。我建议您删除它们以减少对任何绑定生成器的混淆 你试过google.com/search?q=how+to+write+a+python+library+in+c%2B%2B 吗? 【参考方案1】:

在你的情况下,最好保持简单,不要使用绑定生成器,因为你这里只有一个简单的函数,它不接收任何参数,只返回一个 int。

您的目标可以通过以下方式实现:

cpp_reader.cpp 中,在阅读器定义之前添加以下行:

extern "C" __attribute__ ((visibility ("default")))
int reader()

    ....

现在从 Python 你可以简单地做:

from ctypes import cdll
import os
lib = cdll.LoadLibrary(os.path.abspath("libclickhouse-cpp-lib.so"))
num_rows = lib.reader()

另外不要忘记在编译共享对象时将-shared 添加到g++ 命令行

【讨论】:

以上是关于将 C++ 与 Python 连接的主要内容,如果未能解决你的问题,请参考以下文章

将 C++ 程序输出与 Python 脚本链接

UDP 连接没有收到来自服务器的任何回复 - Python(也可能是使用 boost 的 c++)

带有类方法的 Cython 回调

如何编译多个 C++ 文件以将它们与 Python ctypes 一起使用?

带有 python 扭曲服务器的 Qt C++ tcp 客户端

在 C++ 与 Python 中提升权力