То, что возвращает dlsym()
, обычно является указателем функции - замаскированным как void *
. (Если вы спросите его об имени глобальной переменной, он также вернет вам указатель на эту глобальную переменную.)
Затем вы вызываете эту функцию так же, как и любой другой указатель на функцию:
int (*fun)(int, char *) = (int (*)(int, char *))dlsym(triangle, "function");
(*fun)(1, "abc"); # Old school - pre-C89 standard, but explicit
fun(1, "abc"); # New school - C89/C99 standard, but implicit
Я старая школа; Я предпочитаю явную запись, чтобы читатель знал, что fun - это указатель на функцию без необходимости видеть ее объявление. С новой школьной нотацией вы должны не забыть искать переменную 'fun
', прежде чем пытаться найти функцию с именем 'fun()
'.
Обратите внимание, что вы не можете строить вызов функции динамически, как вы это делаете - или вообще не. Для этого требуется гораздо больше работы. Вы должны заранее знать, что ожидает указатель функции в виде аргументов и что он возвращает, и как все это интерпретировать.
Системы, которые управляют более динамическими вызовами функций, такие как Perl, имеют специальные правила о том, как функции вызываются и передаются аргументы, и не вызывают (возможно, не могут вызвать) функции с произвольными сигнатурами. Они могут вызывать только функции с подписями, о которых известно заранее. Один механизм (не используемый Perl) - это поместить аргументы в стек, а затем вызвать функцию, которая знает, как собирать значения из стека. Но даже если вызываемая функция манипулирует этими значениями и затем вызывает произвольную другую функцию, вызываемая функция обеспечивает правильную последовательность вызова для произвольной другой функции.
Отражение в Си сложно - очень тяжело. Это не подлежит отмене, но для этого требуется инфраструктура, которая поддерживает его, и дисциплина для его использования, и он может вызывать только те функции, которые поддерживают правила инфраструктуры.