xvadim_prog (xvadim_prog) wrote,
xvadim_prog
xvadim_prog

Categories:

Свигерство

В заголовке нет ошибки, так как хочу рассказать не о свингерах, а об утилите swig.

Введение


Как известно, подавляющее большинство разнообразных библиотек пишется на языках C и C++. Соответственно, наиболее просто их использовать в программах на этих языках. Однако программирование на компилируемых языках - процесс долгий и печальный. В тоже время существует множество интерпретируемых языков программирования, которые для программиста более удобны. Обычно такие языки содержат механизмы, позволяющие вызывать функции из C/C++-библиотек. Однако эти механизмы у разных языков разные, да и довольно сложные. К счастью, есть инструмент, который в соответствии с правилом “пишите программы, которые пишут программы”, позволяет автоматизировать интеграцию библиотек на C/C++ в другие языки - SWIG.
SWIG поддерживает множество языков: Perl, PHP, Python, Tcl, Ruby, C#, Common Lisp, Java, Lua, Modula-3, OCAML, Octave, R. Рассмотрим применение SWIG для интеграции в PHP C-библиотеки.

Простой пример


Тренироваться будем, как завещал классик, на кошках. Для этого сделаем простую библиотеку, которую будем интегрировать в PHP. Наша библиотека будет иметь следующий вид:

int my_fun(int a, int b)
{
    return a+b;
}

Как сделать из этого текста библиотеку, я рассказывать не буду, ибо “все уже украденонаписано до нас”, например здесь.
Теперь необходимо создать специальный файл, который позволит SWIG’у сгенерировать нужный код:

%module mylibext
int my_fun(int a, int b);

В первой строке задаётся имя модуля расширения для PHP, во второй указывается функция библиотеки, которая будет доступна в данном модуле.
С помощью данного файла уже можно генерировать исходный код расширения:

swig -php mylibext.i

SWIG создаст несколько файлов: mylibext_wrap.c, php_mylibext.h, mylibext.php. Первые два файла используются для компиляции расширения:

gcc ‘php-config --includes’ -fpic -c mylibext_wrap.c
gcc -shared -o mylibext.so mylibext_wrap.o

Для компиляции расширения в Linux системе должен быть установлен пакет php-devel или аналогичный (имя пакета зависит от дистрибутива Linux). Фрагмент php-config --includes заключён в символы слабого ударения (обратные апострофы). Эта команда используется для определения каталога, в котором лежат заголовочные файлы, необходимые для компиляции php-расширений. После компиляции мы получим динамическую библиотеку mylibext.so, которую перед использованием необходимо скопировать в каталог с модулями расширений PHP, например, /usr/lib64/php/modules. Этот каталог можно узнать с помощью команды:

php-config --extension-dir

Загружать созданное расширение можно с помощью функции dl (использование этой функции должно быть разрешено в php.ini). Файл mylibext.php содержит более “умный код” для загрузки этого расширения, т.е. можно не обращатьсянапрямую к dl, а подключить данный файл с помощью include:

<?php
include("mylibext.php");
echo my_fun(3, 4),"\n";
?>

Более сложный пример


Рассмотрим более сложный пример создания модуля расширения. Предположим, что в C-библиотеке есть функция, которая в качестве одного из параметров принимает массив:

int my_array_sum(int size, int *arr)
{
    int s = 0;
    int i;
    for(i = 0; i < size; ++i)
        s += arr[i];
    return s;
}

К сожалению, мы не можем в php-коде просто передать такой функции php-массив. Необходимо использовать специальные массивы, которые создаются вспомогательными функциями, генерируемыми swig’ом. Создает такие функции команда %array_functions:

%array_functions(int, intArray);

Указанная строка создает вспомогательные функции для массивов целых чисел:
new_intArray(size)создает новый массив, в качестве параметра указывается число элементов в массиве
delete_intArray($arr)удаляет массив $arr (освобождает занятую им память)
intArray_setItem($arr, $index, $value)аналог $arr[$index]=$value
intArray_getItem($arr, $index)возвращает значение элемента массива $arr с индексом $index


Для использования команды %array_functions необходимо подключить заголовочный файл carrays.i:

%include “carrays.i”

Таким образом, полный текст входного файла для swig будет иметь следующий вид:

%module mylibext
%include "carrays.i"
%array_functions(int, intArray);
int my_array_sum(int size, int *ar);

Использование расширения с данной функцией приведено ниже:
<?php
include("mylibext.php");
$arr = new_intArray(3);
intArray_setItem($arr, 0, 1);
intArray_setItem($arr, 1, 2);
intArray_setItem($arr, 2, 3);
$s = my_array_sum(3, $arr);
echo $s,"\n";
delete_intArray($arr);
?>

Заключение


SWIG значительно упрощает разработку php-расширений, использующих C/C++-библиотеки.
Tags: programming
Subscribe

  • ЧГК-марафон

    На выходных играл в ЧГК-марафон в Одессе. Как всегда все было организовано замечательно. Играли в ресторане “Арарат”. Причем часть команд играла на…

  • Рецеп приготовления омлета

    1. берем неоплодотворенное яйцо. Дрелью с 8-10-миллиметровым сверлом проделываем в нем отверстие, постоянно сдувая образующуюся пыль. 2.…

  • Хаус, Холмс и др.

    Между Хаусом и Холмсом довольно много параллелей. Оба занимаются расследованиями, у обоих на подхвате врачи, которые выслушивают их идеи (правда, у…

  • Post a new comment

    Error

    default userpic
    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 1 comment