Предотвращение искажения имени в C (не C ++) с MinGW для динамического поиска символов - PullRequest
3 голосов
/ 12 февраля 2011

У меня есть программа на C, где я получаю указатели на функции «динамически» по имени функции (т.е. я передаю имя функции в виде строки и получаю указатель на функцию). Я уже делаю это в Linux, используя dlopen и dlsym, и я полагаю, что это также будет работать в любом другом Unix-подобном с dlfcn .

Проблемы начались, когда я попытался портировать эту программу на Windows, используя MinGW. Когда я пытаюсь найти имя, используя «GetProcAddress (handle, symbol_name), где« symbol_name »- это имя моей функции обратного вызова, а« handle »- дескриптор текущего исполняемого файла, возвращаемого« GetModuleHandle (NULL) », я ничего не получаю потому что искажение имени MinGW добавляет «_» к моему имени символа.

Очевидное решение (префикс «_» к символу, который я хочу) кажется немного «опасным» для переносимости (может ли компилятор добавить два подчеркивания для некоторых из них? Я не знаю), поэтому я спрашиваю:

  • Есть ли лучший способ запретить компилятору искажать имена моих символов? (или их подмножество, только те обратные вызовы, которые мне нужно найти динамически);

  • Или способ заставить GetProcAddress найти их даже в искаженном виде?

Я также попробовал опцию -fno -ading-underscore , но она также убрала искажение всех внешних символов, сделав программу невозможной для связи с stdlib и т. Д. (Также, предупреждения по документации немного страшновато).

Также обратите внимание, что я использую чистый C - в любой части моего кода нет C ++ - и весь мой код находится в одном «.exe».

ТИА

Ответы [ 2 ]

0 голосов
/ 12 февраля 2011

C не использует искажение имени. В частности, он не добавляет никакой информации о типе имени (в отличие от C ++). Но некоторые платформы вносят небольшие изменения в название, например, ставят префикс подчеркивания. И в отличие от C ++, это зависит только от платформы, но не от компилятора.

На всех платформах, которые я видел до сих пор, я не видел ни изменений, ни основного подчеркивания.

Поэтому я предлагаю вам использовать ifdefs , чтобы определить, использует ли текущая платформа подчеркивание или нет.

(В Windows есть еще одна небольшая модификация для некоторых функций Windows API, чтобы отличать ANSI от версии Unicode. Но это, вероятно, не относится к вашему случаю.)

Может быть, кто-то еще может указать на некоторую официальную документацию для C ABI на разных платформах.

0 голосов
/ 12 февраля 2011

Не знаю, в чем ваша проблема, поскольку я не могу воспроизвести ее на простейшем примере DLL, который я могу себе представить:

/* hello_dll.c */
#include <stdio.h>

__declspec(dllexport) void hello ( void )
{
    puts ( "Hello, DLL!");
}

/* hello_exe.c */
#include <windows.h>
#include <stdio.h>  

int main () {
    typedef void (*pfunc)(void);

    HANDLE hself;

    pfunc hello;

    hself = GetModuleHandle(NULL);

    hello = (pfunc)GetProcAddress(hdll, "hello");

    hello();

    return 0;
}

Это командная строка, использующая gcc MinGW без специальных флагов, ивсе это работает:

gcc src\hello_dll.c src\hello_exe.c -o bin\hello.exe
$ bin\hello.exe
Hello, DLL!
$ gcc --version
gcc (GCC) 4.5.0

Это не работает без __declspec(dllexport), если вы получаете функцию от себя;при создании DLL с gcc -shared это не является необходимым, но кажется необходимым при экспорте функции из exe.

...