Можно ли использовать 32битные библиотеки в 64битных программах? Скорее нет. А если очень нужно? Тогда скорее да!
Для одного проекта мне нужно работать с 32битными проприетарными библиотеками. Под виндой нет проблем — компилируем все в 32 бита и вперед. Но под линуксом дела обстоят хуже. Собирать все в 32 бита и цеплять в RPM 32битные версии свободных библиотек некрасиво, более того у меня есть API для плагинов. Совсем не хочется заставлять юзеров ставить ради несчастного плагина 32битный компилятор. Поэтому я решил сделать переходник из кота в мышь, который будет вызывать функции из 32битных библиотеке в отдельном процессе. Сначала я хотел сделать его на питоне, но скомпилировать питон в бинарник у меня не получилось. Потом добрые люди на IRC канале PyPy подсказали мне, что можно использовать libffi прямо из C! Дальше дело за малым.
В итоге получилась программа runso32. Она работает в двух режимах. В первом режиме в аргументах командной строки задается библиотека, функция, строка описания параметров и собственно сами параметры. На данный момент поддерживаются параметры типа int, unsigned int, double, указатель и последовательность байтов (буфер). Программа вызывает функцию, печатает возвратное значение и завершается. Второй вариант — интерактивный. Программа читает команды из стандартного ввода или файла. Сначала регистрируются все интересные нам функции. Потом каждая запись, начинающаяся с «CALL», вызывает функцию с заданным номером. в интерактивном режиме перед тем как отправить буфер необходимо указать его длину. В интерактивном режиме все все величины отсылаются в бинарном формате Little Endian
После того как мы определились какие функции нам нужны, можно сделать 64бит библиотеку. Вызов каждой функции будет отсылать в runso32 идентификатор нужной функции и параметры и получать из runso32 результат. Таким образом, мы как бы вызываем функции из 32бит библиотеки в 64бит приложении. Это происходит хоть и с задержкой, но практически незаметно для остальной программы.
Вроде бы все готово, но программный интерфейс получился слишком громоздким. Тогда я написал 64битную библиотеку, которая регистрирует функции и позволяет их вызывать несколько проще. Теперь нам нужна только одна функция — versatile_call. Однако, прежде чем ее использовать, необходимо заполнить в глобальной структуре, имя библиотеки, имена функций и строки описания параметров. Эта структура должна быть заполнена при компиляции. Дальше необходимо всего лишь вызвать функцию versatile_call(n, ...), где n — номер нужной функции из 32бит и дальше список параметров, не забываем про длину буфера, а последний аргумент это указатель на переменную, в которой будет записано возвращаемое значение.
Исходники и RPM лежат здесь: sourceforge.net/projects/runso32
Автор: SiTLar