dlsym/dlopen с аргументами во время выполнения

см. этот ответ также:

Это - относительно мягкий & корректное решение.
, Почему мой терминал невидим после уменьшения его и как я могу найти его?
заключение в кавычки:

Использование сочетание клавиш Super + W для показа графического обзора всех окон, включая терминал (терминалы); просто нажмите на тот, который Вы хотите поднять его.

(Super ключ = Win ключ)

у меня была подобная проблема, которая происходит, когда Терминал разблокирован от средства запуска

  • с минимизированными Терминальными сеансами или
  • путем уменьшения любого Окна терминала позже

, открытые окна часто не связаны с Терминальным средством запуска даже при том, что это использовалось для запуска их.

Другой неуклюжий и неэлегантный метод, который я использовал, перезагружает X-окна и следовательно Единицу путем ввода Высокого звука + Print Screen + K , чтобы уничтожить и перезапустить X-окна.

x-ref: окно терминала исчезает после того, как я минимизирую его

6
задан adk 30 August 2009 в 18:28
поделиться

2 ответа

На самом деле, вы можете делать почти все, что хотите. В языке C (в отличие, например, от C ++) на функции в общих объектах ссылаются просто по их именам. Итак, чтобы найти - и, что наиболее важно, вызвать - нужную функцию, вам не нужна ее полная подпись. Вам нужно только его название! Это одновременно и преимущество, и недостаток - но такова природа выбранного вами языка.

Позвольте мне продемонстрировать, как это работает.

#include <dlfcn.h>

typedef void* (*arbitrary)();
// do not mix this with   typedef void* (*arbitrary)(void); !!!

int main()
{
    arbitrary my_function;
    // Introduce already loaded functions to runtime linker's space
    void* handle = dlopen(0,RTLD_NOW|RTLD_GLOBAL);
    // Load the function to our pointer, which doesn't know how many arguments there sould be
    *(void**)(&my_function) = dlsym(handle,"something");
    // Call something via my_function
    (void)  my_function("I accept a string and an integer!\n",(int)(2*2));
    return 0;
}

Фактически, вы можете вызывать любую функцию таким образом. Однако есть один недостаток. На самом деле вам нужно знать тип возвращаемого значения вашей функции во время компиляции . По умолчанию, если вы опускаете void * в этом typedef, int считается возвращаемым типом - и да, это правильный код C. Дело в том, что компилятор должен знать размер возвращаемого типа для правильной работы со стеком.

Вы можете обойти это с помощью уловок, например, заранее объявив несколько типов функций с разными размерами возвращаемых типов и затем выберите, в какой из них вы действительно собираетесь позвонить. Но более простое решение - потребовать от функций в вашем плагине всегда возвращать void * или int; фактический результат возвращается через указатели, заданные в качестве аргументов.

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

21
ответ дан 8 December 2019 в 02:19
поделиться

То, что возвращает 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

I я старая школа; Я предпочитаю явную нотацию, чтобы читатель знал, что «развлечение» - это указатель на функцию, без необходимости видеть ее объявление. В новой школьной нотации вы должны не забыть искать переменную ' fun ', прежде чем пытаться найти функцию с именем ' fun () '.

Обратите внимание, что вы не можете Постройте вызов функции динамически, как вы это делаете - или не в целом. Для этого потребуется гораздо больше работы. Вы должны заранее знать, что указатель функции ожидает в виде аргументов, что он возвращает и как все это интерпретировать.

Системы, которые управляют более динамическими вызовами функций, такие как Perl, имеют особые правила о том, как функции вызываемые и аргументы передаются и не вызывают (возможно, не могут вызывать) функции с произвольными подписями. Они могут вызывать только функции с заранее известными подписями. Один из механизмов (не используемый Perl) заключается в том, чтобы поместить аргументы в стек, а затем вызвать функцию, которая знает, как собирать значения из стека. Но даже если эта вызываемая функция манипулирует этими значениями, а затем вызывает произвольную другую функцию, эта вызываемая функция обеспечивает правильную последовательность вызова для произвольной другой функции.

Отражение в C сложно - очень сложно.

19
ответ дан 8 December 2019 в 02:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: