Взаимодействие C с Python

#c #python-3.x #ctypes #swig #boost-python

#c #python-3.x #ctypes #глоток #boost-python

Вопрос:

У меня есть библиотека c (C 17) и функция, зависящая от этой библиотеки. Я хочу вызвать эту функцию из python (python 3). Как это можно сделать?

Я прочитал несколько руководств по использованию swig и ctypes, но я не знаю, как я могу заставить его работать для внешней разделяемой библиотеки.

Подробности: у меня есть это libclickhouse-cpp-lib.so файл .so и заголовочные файлы для этой библиотеки находятся в каталоге /path/to/header/files .

 /*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",
        [amp;numrows] (const Blockamp; 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",
        [amp;numrows] (const Blockamp; 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/путь/к/заголовочным/файлам -I/usr/include/python3.6m/ -L. /путь/к/libclickhouse-cpp-lib.so -o outfile

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/so_file/экспорт каталога
LD_LIBRARY_PATH

каталог /path/to/so_file/ содержит libclickhouse-cpp-lib.so

./outfile

Комментарии:

1. по моему опыту, pybind11 — самый простой способ. boost.python также подходит, если вы уже используете Boost. Я бы не рекомендовал ctypes , если вы просто не занимаетесь хобби-проектами, и я бы не рекомендовал swig , если вам не нужно использовать свой C для множества других языков в дополнение к Python.

2. Я не вижу причин для cpp_reader.h #include <clickhouse/client.h> или даже iostream . Я предлагаю вам удалить их, чтобы уменьшить путаницу в любом генераторе привязки

3. Вы пробовали google.com/search ? вопрос= как записать библиотеку python в c++ ?

Ответ №1:

В вашем случае, возможно, лучше сохранить его простым и не использовать генераторы привязки, потому что все, что у вас здесь есть, — это простая функция, которая не получает никаких параметров и просто возвращает int .

Ваша цель может быть достигнута следующим образом:

В cpp_reader.cpp , добавьте следующую строку перед определением reader:

 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 командную строку при компиляции общего объекта