Подтвердить что ты не робот

Ctypes - Новичок

У меня есть задача "обернуть" библиотеку c в класс python. Документы невероятно расплывчаты по этому вопросу. Кажется, они ожидают, что только продвинутые пользователи python будут реализовывать ctypes. Ну, я новичок в python и нуждаюсь в помощи.

Некоторая пошаговая помощь была бы замечательной.

Итак, у меня есть моя библиотека c. Что я делаю? Какие файлы я размещаю где? Как импортировать библиотеку? Я читал, что может быть способ "автоматической обертки" на Python?

(Кстати, я сделал учебник ctypes на python.net, и это не сработало. То есть я думаю, что они предполагают, что я смогу заполнить остальные шаги.

Фактически это ошибка, которую я получаю с их кодом:

File "importtest.py", line 1
   >>> from ctypes import *
   SyntaxError: invalid syntax

Я мог бы действительно использовать пошаговую помощь по этому поводу! Благодаря ~

4b9b3361

Ответ 1

Вот быстрый и грязный учебник ctypes.

Сначала напишите свою C-библиотеку. Вот простой пример Hello:

testlib.c

#include <stdio.h>

void myprint(void);

void myprint()
{
    printf("hello world\n");
}

Теперь скомпилируйте его как общую библиотеку (mac fix, найденную здесь):

$ gcc -shared -Wl,-soname,testlib -o testlib.so -fPIC testlib.c

# or... for Mac OS X 
$ gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC testlib.c

Затем напишите обертку, используя ctypes:

testlibwrapper.py

import ctypes

testlib = ctypes.CDLL('/full/path/to/testlib.so')
testlib.myprint()

Теперь выполните его:

$ python testlibwrapper.py

И вы должны увидеть вывод

Hello world
$

Если у вас уже есть библиотека, вы можете пропустить не-python часть учебника. Убедитесь, что ctypes может найти библиотеку, поместив ее в /usr/lib или другой стандартный каталог. Если вы это сделаете, вам не нужно указывать полный путь при написании обертки. Если вы решите не делать этого, вы должны указать полный путь библиотеки при вызове ctypes.CDLL().

Это не место для более полного руководства, но если вы попросите о помощи с конкретными проблемами на этом сайте, я уверен, что сообщество поможет вам.

PS: Я предполагаю, что вы работаете в Linux, потому что вы использовали ctypes.CDLL('libc.so.6'). Если вы находитесь на другой ОС, все может немного измениться (или довольно много).

Ответ 2

Во-первых: Код >>>, который вы видите в примерах python, - это способ указать, что это код Python. Он использовался для ветки кода Python от вывода. Вот так:

>>> 4+5
9

Здесь мы видим, что строка, начинающаяся с >>>, - это код Python, а 9 - результат. Именно так выглядит, если вы начинаете интерпретатор Python, поэтому он так и сделал.

Вы никогда не вводите часть >>> в файл .py.

Это позаботится о вашей синтаксической ошибке.

Во-вторых, ctypes - это всего лишь один из нескольких способов обтекания библиотек Python. Другими способами являются SWIG, которые будут смотреть на вашу библиотеку Python и генерировать модуль расширения Python C, который предоставляет C API. Другой способ - использовать Cython.

Все они имеют преимущества и недостатки.

SWIG откроет только ваш API C на Python. Это означает, что вы не получаете никаких объектов или чего-то еще, вам придется сделать отдельный файл Python, который сделает это. Однако, как правило, существует модуль, называемый "wowza", и модуль SWIG, называемый "_wowza", который является оберткой вокруг API C. Это хороший и простой способ делать вещи.

Cython создает файл C-Extension. Преимущество состоит в том, что весь написанный вами код Python сделан на C, поэтому объекты, которые вы пишете, также находятся на C, что может быть улучшением производительности. Но вам нужно будет узнать, как он взаимодействует с C, поэтому немного поработайте над тем, как его использовать.

ctypes имеет то преимущество, что C-код не компилируется, поэтому очень удобно использовать для упаковки стандартных библиотек, написанных кем-то еще, и уже существует в двоичных версиях для Windows и OS X.

Ответ 3

Ответ Chinmay Kanchi превосходный, но мне нужен пример функции, которая передает и возвращает переменную из кода С++. Я бы включил его здесь, если это полезно другим. Код С++ для функции, которая принимает целое число и добавляет его к возвращаемому значению,

extern "C" int add_one(int i)
{
    return i+1;
}

Сохранено как файл test.cpp, обратите внимание на обязательный extern "C" (это можно удалить для кода C). Это скомпилировано с использованием g++, с аргументами, аналогичными ответам Chinmay Kanchi,

g++ -shared -o testlib.so -fPIC test.cpp

Код Python использует load_library из numpy.ctypeslib, предполагая путь к общей библиотеке в том же каталоге, что и Python script,

import numpy.ctypeslib as ctl
import ctypes

libname = 'testlib.so'
libdir = './'
lib=ctl.load_library(libname, libdir)

py_add_one = lib.add_one
py_add_one.argtypes = [ctypes.c_int]
value = 5
results = py_add_one(value)
print(results)

Отпечатает 6, как ожидалось.