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