Вызывать имя функции, а не указатель функции

На странице man для libffi есть пример, который, по сути, требует указателя на функцию (в этом примере, puts).

Однако, что мне делать, если я знаю только имя функции, но на самом деле у меня нет указателя (что обычно происходит, если ffi используется, скажем, в динамических языках программирования)?

Скажем, я хочу сделать что-то вроде этого (псевдокод):

cif = null
s = "Hello World"
args = []
values = []
args[0] = ffi.type_pointer
values[0] = address_of(s)
if(ffi.prepare(cif, ffi.DEFAULT_ABI, ffi.type_uint, args)):
     ffi.call(cif, "puts", values)

Короче говоря, я хочу, чтобы libffi динамически просматривал функцию (если она поддерживается ffi, в первую очередь), похожую на dlfcn/LoadLibrary, а затем вызывал ее с помощью предоставленных типов FFI CIF.

Возможно ли такое с libffi? Как будет выглядеть простой пример?

1 ответ

Решение

Есть две возможности - одна, требующая обдумывания со стороны программиста.

В зависимости от o / s, существуют средства, связанные с общими библиотеками для поиска символов из программы или ее общих библиотек.

Во многих системах Unix и, в частности, в Linux средства объявлены в <dlfcn.h> и являются dlopen() а также dlsym() (а также dlclose(), так далее). При наличии соответствующего дескриптора для разделяемой библиотеки, вы можете использовать:

int (*ffi_ptr)(const char *) = dlsym(ffi_handle, "ffi_function_name");

Вы должны рассмотреть кастинг - обычно жестокий - чтобы избежать предупреждений компиляции.

Альтернативный, заранее продуманный метод заключается в создании таблицы имен функций и указателей функций, в которой вы можете искать имя и использовать соответствующий указатель:

struct ptr_function
{
    void (*func_ptr)(void);
    const char *func_name;
};

static const struct ptr_function[] =
{
    { func_1, "func_1"       },
    { func_2, "func_2"       },
    { func_2, "func_synonym" },
};

enum { NUM_PTR_FUNCTION = sizeof(ptr_function) / sizeof(*ptr_function) } ;

Обратите внимание, что этот метод учитывает синонимы таким образом, что dlsym() Механизм нет. Тем не менее, премедикация часто является основным камнем преткновения. Это метод, который восходит к 80-м и началу 90-х годов, когда общие библиотеки не были доступны повсеместно. Еще раз, необходимость в приведениях может сделать код несколько более сложным.

Другие вопросы по тегам