Я создаю привязки Haskell для библиотеки C. Тем не менее, я хочу адаптировать вызывающие соглашения библиотеки к чему-то более подходящему для Haskell, поэтому я создал класс шаблонов, который имеет статический метод, который вызывает правильный метод, когда вы используете его следующим образом:
Wrap<decltype(&libraryFunction), &libraryFunction>::call(...);
Где ...
обозначает аргументы. Это здорово, компилятор создал для меня код оболочки. Я даже могу взять адрес этой функции с помощью оператора &
поэтому, по-видимому, это просто регулярная функция.
Тем не менее, Haskell не может использовать шаблоны C++, поэтому я хотел бы явно создать этот шаблон для требуемых функций и экспортировать их как обычную функцию C, которую я могу ссылаться на Haskell. Я знаю, что могу просто сделать заглушки, которые вручную вызывают эту статическую функцию-член, но пусть говорят, что мне это действительно не нравится.
Есть идеи, как это сделать? Портативный или не портативный, я хотел бы знать, если это возможно.
Это невозможно сделать портативно:
[Temp]/4
Шаблон, явная специализация шаблона и частичная специализация шаблона шаблона не должны иметь C-ссылки.
Обратите внимание, что это также мешает вам использовать указатель на эту функцию, позволяя Haskell вызывать функцию через этот указатель: не гарантируется, что, например, соглашение о вызове функции C++ (в программе C++) совпадает с Haskell предполагает для указателя функции, который он получает.
Что можно сделать портативно - это экспортировать одну внешнюю функцию extern "C"
которая переводит между языковыми связями между C и C++. Вы можете передавать указатели функций или другие типы идентификаторов в Haskell, а Haskell называет эту единственную функцию C, передающую идентификатор функции, которую он фактически хочет вызвать:
std::map<int, void(*)(int32_t)> functions;
extern "C" interface_fct(int id, int32_t arg)
{
functions[id](arg);
}
Это, конечно, не очень полезно для функций с разными наборами параметров.
Вы можете написать что-то похожее на va_args
(но более безопасное), чтобы передать произвольные аргументы, но было бы более полезно писать что-то непереносимое.
extern "C"
?