ФЭНДОМ


Squeak умеет вызывать внешние библиотеки (DLL и т.д.) с помощью механизма FFI (Foreign Function Interface).

Чтобы вызвать внешнюю функцию, нужно сделать отдельный метод (обычно названия таких методов начинаются с 'api', например 'apiFillCRect:with:'). Структура метода похожа на структуру методов, вызывающих именованные примитивы. Первой строкой должно идти описание внешней функции. За ней идёт обычный Smalltalk-код, который исполняется, если вызов внешней функции произошёл с ошибкой.

Так как API-вызовы не знают, как сообщить об ощибке (как это делают примитивы Squeak), то "ошибка" в данном случае означает, что не удалось подключить внешнюю билиотеку или вызвать внешнюю функцию, а не то, что внешняя функция не смогла выполнить свою задачу. Поэтому чаще всего в качестве Smalltalk-кода здесь используется '^self externalCallFailed.'

Пример метода из образа 3.8-6665, в классе MacRect:

 apiFillCRect: r with: pat
 	<apicall: void 'FillCRect' (MacRect* MacPixPatPtr*) module:'InterfaceLib'>
 	^self externalCallFailed

Описание внешней функции заключается в угловые скобки ( < и > ). Внутри скобок 'apicall:' обозначает FFI-вызов. За 'apicall:' идёт тип данных, возвращаемых функцией (в примере - 'void'), строка с названием функции ('FillCRect'), список типов аргументов ('MacRect*' и 'MacPixPatPtr*'), 'module:' и, наконец, строка с именем библиотеки, в которой находится вызываемая функция ('InterfaceLib').

Кроме конструкции <apicall:> существует также конструкция <cdecl:>, которая полностью аналогична <apicall:>, за исключением способа вызова внешней функции. <apicall:> использует Pascal-евские соглашения о вызове функций (аргументы складываются в стек слева направо, убирает их из стека вызываемый), а <cdecl:> - C-шные соглашения о вызове (аргументы складываются в стек справа налево, убирает их из стека вызывающий).