Руководства по реализации интерфейса сторонней функции

Прямо сейчас я работаю над языком сценариев, у которого еще нет FFI. Я хотел бы знать, как удобнее всего это сделать, предполагая, что я хотел бы написать это, как это делают крутые гики - я хотел бы написать FFI на самом языке сценариев.

Язык программирования, с которым мне нужно работать, — C. Итак, если говорить об основах, я знаю, что libdl.so — мой лучший друг. Очевидно, это не единственное, что мне понадобится, но самое важное из них.

У меня есть только слабое представление о том, что еще мне нужно для этого. Я хотел бы получить от FFI такое же поведение, как у ctypes python.

Что мне нужно знать, чтобы зайти так далеко? Я знаю, что со структурами данных есть серьезная магия, с которой мне придется иметь дело. Как мне управлять этим, чтобы я мог делать большую часть этой серьезной магии на самом языке сценариев? Я бы использовал такую ​​магию для гораздо большего, чем просто интерфейс внешней функции. Например, я мог бы захотеть передать C-подобные двоичные данные в файлы.


person Cheery    schedule 22.07.2009    source источник


Ответы (2)


Я думаю, что правильный ответ требует подробного эссе.

По сути, должны быть оболочки для загрузки библиотек и средств поиска символов, предоставляемых хост-ОС. Если основные типы данных вашего языка внутренне представлены одной структурой данных C, то к разработчикам библиотеки может быть предъявлено требование, чтобы параметры и возвращаемый тип экспортируемых функций C были объектами этой структуры данных. Это упростит обмен данными. Если в вашем языке есть некоторая форма шаблонных выражений и функций первого класса, то сигнатура функций C может быть записана в виде шаблонов, и библиотека будет искать функцию, соответствующую эквивалентной сигнатуре. Вот некоторый псевдокод функции C и ее использование в скрипте:

/* arith.dll */
/* A sample C function callable from the scripting language. */

#include "my_script.h" // Data structures used by the script interpreter.

My_Script_Object* add(My_Script_Object* num1, My_Script_Object* num2)
{
   int a = My_Script_Object_To_Int(num1);
   int b = My_Script_Object_To_Int(num2);
   return Int_To_My_Script_Object(a + b);
}

/* End of arith.dll */

// Script using the dll
clib = open_library("arith.dll");

// if it has first-class functions
add_func = clib.find([add int int]);
if (cfunc != null)
{
   sum = add_func(10, 20);
   print(sum);
}

// otherwise
print(clib.call("add", 10 20));

Здесь невозможно обсуждать дополнительные детали реализации. Обратите внимание, что мы ничего не сказали о сборке мусора и т. д.

Источники, доступные по следующим ссылкам, могут помочь вам двигаться дальше:

http://common-lisp.net/project/cffi/ http://www.nongnu.org/cinvoke/

person Vijay Mathew    schedule 23.07.2009
comment
Спасибо. Хотя описанная вещь была бы самой простой, она также вынудила бы меня писать С-части к привязкам. Я думаю, что это неприемлемо для моих нужд. - person Cheery; 23.07.2009
comment
Ссылка, которая была размещена в этом вопросе, кажется, не работает - почему это? - person Anderson Green; 02.11.2012

Посетите http://sourceware.org/libffi/.

Помните, что соглашения о вызовах будут разными для разных архитектур, т. е. в каком порядке переменные функции помещаются в стек. Я не знаю, как написать это на вашем собственном языке сценариев, я знаю, что Java JNI использует libffi.

person Sean A.O. Harney    schedule 25.07.2009