Руководства для реализации интерфейса иностранной функции
Вопрос
Прямо сейчас я работаю над языком сценариев, у которого еще нет FFI. Я хотел бы знать, какой самый удобный способ получить его, предполагая, что я хотел бы написать это, как это делают крутые гики - я хотел бы написать FFI на самом языке сценариев.
Язык программирования, который мне нужен для взаимодействия, является C. Поэтому для оснований я знаю, что Libdl.SO - мой лучший друг. Очевидно, это не единственное, что мне нужно, но самое важное из них.
У меня есть только небольшие представления о том, что еще мне нужно для этого. Я хотел бы получить аналогичное поведение от FFI, как и то, что имеет Python Ctypes.
Что мне нужно знать, чтобы зайти это далеко? Я знаю, что есть какая -то серьезная магия со структурами данных, с которыми мне нужно иметь дело. Как мне это управлять, чтобы я мог сделать большую часть этой серьезной магии в самом языке сценариев? Я бы использовал из такой магии гораздо больше, чем просто интерфейс иностранной функции. Например, я бы захочет передать C-подобные бинарные данные в файлы.
Решение
Я думаю, что для одобрения ответа требуется Подробное эссе.
По сути, должны быть обертки для библиотеки загрузки и поисков символов, предоставленных ОС хост. Если основные данные дата вашего языка внутренне представлены с помощью одной структуры данных 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/
Другие советы
Проверить http://sourceware.org/libffi/
Помните, что призывные конвенции будут разными в разных архитектурах, то есть какие переменные функции порядка выпадают в стек. Я не знаю о написании его на своем собственном языке сценариев, я знаю, что Java JNI использует Libffi.