Caché Native Access - the way to call native binary libs from Caché Object Script in a very easy and robust way
Способ работы с нативными библиотеками любых ОС из Caché Object Script наиболее простым и удобным способом, без создания специальных Callout библиотек.
Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...
Caché Native Access. InterSystems Meetup 2014
1. Caché Native Access
Новый механизм вызова сторонних
библиотек
Дмитрий Трефилов
Санкт-Петербург, 2014
2. История вопроса (RegEx)
это было давно и неправда…
• PCRE – Perl Compatible Regular Expressions
• “The PCRE library is a set of functions that implement regular
expression pattern matching using the same syntax and
semantics as Perl 5. PCRE has its own native API, as well as a
set of wrapper functions that correspond to the POSIX regular
expression API. The PCRE library is free, even for building
proprietary software.”
• ~ 30 нужных экспортируемых функций
• Задача не была завершена
3. История вопроса (ShellExecute)
ближе к истине
• Shell32.DLL
• lpOperation =
– edit
• Launches an editor and opens the document for editing. If lpFile is not a document file, the
function will fail.
– explore
• Explores a folder specified by lpFile.
– find
• Initiates a search beginning in the directory specified by lpDirectory.
– open
• Opens the item specified by the lpFile parameter. The item can be a file or folder.
– print
• Prints the file specified by lpFile. If lpFile is not a document file, the function fails.
– NULL
• The default verb is used, if available. If not, the "open" verb is used. If neither verb is available,
the system uses the first verb listed in the registry.
4. Что такое Callout…
…и с чем его едят
• Встроенный механизм для вызова внешних библиотек (исполняемого кода)
• Требует создания промежуточного модуля, созданного по определенным
правилам
• Является посредником для вызова внешних функций
– ~ 10000 экспортов функций в Windows 7
– ~ 50000 в Linux (RHEL 6)
• Статический подход
– Компиляция ядра Caché
• Динамический подход
– Загрузка библиотек и вызов функций «на лету»
• Недостатки
– Требуются исходный код и настроенное окружение
– Каждый раз необходима перекомпиляция и тестирование
5. Что такое Callout… (часть 2)
Существующая реализация («из коробки»)
void Function1(arg1) char * Function2() int FunctionN(a, b)
ZFENTRY
Function1
ZFENTRY
Function2
ZFENTRY
FunctionN
Caché
7. libFFI
https://sourceware.org/libffi/
• FFI stands for Foreign Function Interface. A foreign function
interface is the popular name for the interface that allows code
written in one language to call code written in another language.
The libffi library really only provides the lowest, machine
dependent layer of a fully featured foreign function interface. A
layer must exist above libffi that handles type conversions for
values passed between the two languages.
• The libffi library provides a portable, high level programming
interface to various calling conventions. This allows a
programmer to call any function specified by a call interface
description at run-time.
8. libFFI (Part 2)
Open Source and Ported to Many Different Platforms
ОС Arch Linux Windows
Cygwin
Windows
MingW iOS Mac OS X FreeBSD Solaris Tru64 AIX OpenBSD AMIGA OS/2 HURD IRIX
AArch64
(ARM64)
Alpha
ARM
AVR32
IA-‐64
MIPS
MIPS64
PowerPC
PowerPC
32-‐bit
PowerPC
64-‐bit
SPARC
SPARC64
TILE-‐Gx/TILEPro
X86
X86-‐64
Xtensa
9. Наш вариант
совмещаем полезное с приятным
Caché
COS Callout Gateway
Диспетчер
Библиотека :
ИмяФункции (Аргументы…)
libFFI libCNA
ИмяФункции (Аргументы…)
void Function1(arg1) char * Function2() int FunctionN(a, b)
10. Применение
+100500 вариантов
• Внешний движок регулярных выражений
• Обработка изображений
• Распознавание и конвертация данных
• Компьютерное зрение
• Научные вычисления
• Работа с аудио/видео
• Криптография
• …
12. Caché Native Access
Схема работы
Caché Callout Gateway libcna
libffi
external library
Класс
CNA
13. Caché Native Access
Что это?
• CNA — связка класса Caché и библиотеки,
написанной на С
• CNA — интерфейс для вызова функций из
любых динамических библиотек
• Ничего, кроме COS, для вызова функций не
нужно
• Цель CNA — расширение функциональности
Caché за счет существующих библиотек
14. Caché Native Access
Что есть сейчас? Caché Callout Gateway
• $ZF(-1) , $ZF(-2)
• Позволяют вызывать системные команды и
консольные программы
• Недостатки:
– Сильно ограничена передача аргументов
– Нет всей функциональности библиотек
15. Caché Native Access
Что есть сейчас? Caché Callout Gateway
• $ZF(-3) , $ZF(-5), $ZF( )
• Позволяют вызывать динамические и статические библиотеки
специального вида (Callout Libraries)
• Недостатки:
– Чтобы сделать из обычной библиотеки Callout Library необходимо:
• Иметь доступ к исходному коду
• Иметь настроенное окружение для сборки
• Для каждой функции прописать некоторое формальное описание
– Поддерживается очень ограниченный набор типов (int и указатели),
16. Caché Native Access
Возможности
• Можно вызывать функции из любой динамической
библиотеки, бинарно совместимой с C
• Поддержка всех простых типов языка C, size_t
и
указателей
• Поддержка структур (и вложенных структур)
• Поддержка потоков Caché
• Работает на Linux (x86-32/64), Windows (x86-32/64)
17. Caché Native Access
• Linux:
– make
libffi
&&
make
• Windows
– make
libffi
&&
make
в mingw или mingw-w64
– или можно загрузить бинарные файлы
• Импортируем файл cna.xml
– do
$system.OBJ.Load("путь
к
cna.xml",
"c")
Установка
19. Caché Native Access
Пример работы с CNA
set
cna
=
##class(CNA.CNA).%New("libcna.dll")
do
cna.LoadLibrary("C:Windowssystem32msvcrt.dll")
set
string
=
cna.ConvertStringToPointer("Hello")
set
argTypes
=
$lb(cna.#POINTER)
set
result
=
cna.CallFunction("strlen",
cna.#SIZET,
argTypes,
string)
write
result,
!
do
cna.FreeLibrary()
size_t
strlen(const
char
*str);
21. Caché Native Access
Подробности реализации
• CNA основывается на libffi
– libffi – интерфейс для вызова внешних функций
– libffi поддерживает различные соглашения о вызове (calling
conventions)
• libffi – библиотека, написанная на C
– То есть, для доступа в libffi из Caché, нужно использовать
Callout Gateway
• CNA – Callout Library и оболочка (wrapper) над libffi
22. Caché Native Access
Получение адреса функции
• Мы хотим вызывать функцию, используя ее имя
• Однако, для использования libffi нужен адрес функции
• Чтобы получить адрес нужно использовать
платформо-зависимые интерфейсы: POSIX и WinAPI
– Функции dlopen()
и dlsym()
из POSIX
– Функции LoadLibrary()
и GetProcAddress()
из WinAPI
23. Caché Native Access
Преобразование данных
• Проблема:
– Callout Gateway поддерживает очень мало типов данных
• Решение:
– преобразовывать данные на стороне Caché
– в CNA передавать строки с бинарными данными в формате языка C
25. Ссылки на ресурсы
полезные и не очень J
• Исходный код CNA и всех примеров выложен на github под
лицензией MIT
– https://github.com/intersystems-‐ru/cna
• Документация по Caché Callout
– http://docs.intersystems.com/cache20141/csp/docbook/
DocBook.UI.Page.cls?KEY=BGCL
• libFFI
– https://sourceware.org/libffi/
26. Планы
которых громадьё…
• %DispatchXXX и более удобная обвязка на стороне COS
• Пополнение примеров
• Расширение списка типов и платформ
• …
Используйте!
Делитесь успехами!