Native C Calls

Акцентирование темы предыдущего поста вызвало ассоциации с этой темой. В принципе, PicoLisp можно запустить и независимо от какой-либо операционной системы, тем не менее автор основывается, как на хосте, на системе POSIX, а значит и C, для вызова библиотек и функций которого имеется соответствующая функция native
(native 'cnt1|sym1 'cnt2|sym2 'any 'any ..) -> any
Первый аргумент должен указывать общую библиотеку объектов, либо "@
" (текущая основная программа), sym1
(имя пути к библиотеке) или cnt1
(дескриптор библиотеки, полученный предыдущим вызовом). Второй аргумент должен быть именем символа sym2
или дескриптором функции cnt2
, полученным предыдущим вызовом). На практике первые два аргумента всегда будут передаваться как временные символы, которые получат дескриптор библиотеки и дескриптор функции, назначенные в качестве значений для кэширования и использования в последующих вызовах. Третий аргумент any
— это спецификация результата, в то время как все последующие аргументы — это аргументы нативной функции. Функциональность подробно описана в Native C Calls.
Спецификация результата может быть либо одним из атомов
NIL void
B byte # Byte (unsigned 8 bit)
C char # Character (UTF-8, 1-4 bytes)
W short # Word (signed 16 bit)
I int # Integer (signed 32 bit)
N long # Number (signed 64 bit)
P void* # Pointer (unsigned 64 bit)
S string # String (UTF-8)
-1.0 float # Scaled fixpoint number
+1.0 double # Scaled fixpoint number
T # Direct Lisp value
или вложенным списком этих атомов с указанием размера для обозначения массивов и структур, например
(N . 4) # long[4]; -> (1 2 3 4)
(N (C . 4)) # {long; char[4];} -> (1234 ("a" "b" "c" NIL))
(N (B . 7)) # {long; byte[7];} -> (1234 (1 2 3 4 5 6 7))
Что может быть аргументами смотрите далее в описании функции …
То есть функция находит библиотеку по имени, находит функцию по имени в библиотеке, преобразовывает аргумент(ы) функции из Lisp в структуры данных C, вызывет код функции на C, преобразовывает возвращаемое значение(я) функции из C в структуры данных Lisp. Прямое возвращаемое значение native — это представление Lisp возвращаемого значения функции C. Дополнительные значения, возвращаемые по ссылке из функции C, доступны в переменных Lisp (значениях символов).
Соответственно, вызов нативных функций С может быть и классификатором с выделением списка, используемых функций - native struct %@ lisp adr errno
struct — это вспомогательная функция, которая может использоваться для управления структурами данных C в памяти. Может потребоваться скаляр (числовое представление значения C) для преобразования его в элемент Lisp или (чаще) указатель на область памяти для построения и извлечения структур данных. lisp позволяет устанавливать функции обратного вызова, вызываемые из кода C, написанного на Lisp.
%@ — это удобная функция, упрощающая наиболее распространенный вариант использования native.
В сочетании эти функции могут связать PicoLisp, практически, с любой функцией C.
Вышеуказанные шаги полностью динамические; нативный код не имеет (и не требует) априорных знаний о библиотеке, функции или задействованных данных. Нет необходимости писать какой-либо связующий код, интерфейсы или включаемые файлы. Все функции можно даже вызывать интерактивно из REPL.
Subscribe to my newsletter
Read articles from Sergey Shishkin directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Sergey Shishkin
Sergey Shishkin
Всегда чему-то учусь!