1. Жесткий, универсальный и «написать один раз, запускай везде» подход:
Ваш язык программирования навязывает пользователю каким-то образом обеспечить объявления функций C, которые будут использоваться (а также их реализации, наиболее вероятно, как динамически связываемая/загружаемая библиотека). Ваш парсер/компилятор/интерпретатор языка программирования интерпретирует подпись функции и, возможно, использует библиотеку интерфейсов внешних функций, такую как libFFI, для совершения вызовов, которые подчиняются соглашениям о вызове ABI и C на платформе. Таким образом, вы можете вызывать любую функцию C из вашего языка без записи привязок.
Этот метод используется в нескольких языках программирования, например PyObjC - это библиотека, которая позволяет программистам на Python напрямую обращаться к API Objective-C с Python.
2. Простой, не четного близко к универсальным и «писать столько раз, сколько вы хотите использовать его» путь:
Вам требуется пользователю языка программирования, чтобы написать C с сигнатурой, указанной заранее, i. е. все расширения языка программирования должны выглядеть
GenericValueType *extension_function(int argc, GenericValueType **argv);
, а затем тот, кто хочет подключить какой-либо другой код языка программирования должно написать привязок с использованием функции и специального API вашего языка программирования. Например, если вы хотите использовать функцию strlen()
из стандартной библиотеки C, можно было бы написать это (pseudoo-) код:
GenericValueType *my_ext_strlen(int argc, GenericValueType **argv)
{
GenericValueType *arg1 = argv[0];
const char *input = ValueToCString(arg1);
size_t len = strlen(input);
return NewValueFromInteger(len);
}
Это проще реализовать для создателя языка, но, как я уже говорил это раньше, это не универсально - каждая функция должна быть привязана/портирована, чтобы быть совместимой. Это подход, который использует большинство языков сценариев, например Python, PHP и Lua требуют привязки к внешним библиотекам, которые должны быть написаны таким образом.
Вы спрашиваете, как лучше всего разработать свой язык для совместимости C? Как и какие функции будут хорошо работать с C interop, а какие нет и каков будет лучший синтаксис и семантика для FFI? Или вы спрашиваете, как его реализовать? В первом случае нам нужно будет узнать намного больше о вашем языке. Это статически или динамически типизировано? Какие расширенные типы он поддерживает? И так далее. В последнем случае мы, по крайней мере, должны были бы знать, пишете ли вы интерпретатор или компилятор. – sepp2k
Просто реализация - казалось бы, после прочтения ответа Эрнеста, что компилятор может быть проще для создания той же сборки. – sdasdadas