Принудительное искажение имени в x64 DLL

Я портирую 32-битное приложение на 64-битное. Приложение поддерживает плагины, которые являются DLL. К сожалению, одна из обязательных функций, которую должен иметь каждый плагин, называется FreeLibrary что, конечно, противоречит kernel32 API с тем же именем. Причина, по которой мой плагин API использует FreeLibrary имя заключается в том, что приложение возникло на другой платформе, где FreeLibrary не конфликтует с какими-либо ОС API.

Однако даже на 32-битной Windows FreeLibrary это не проблема, потому что 32-битные DLL используют искажение имени, т.е. функция хранится как _FreeLibrary и, следовательно, не конфликтует с kernel32 API.

На 64-битной, однако, у меня сейчас проблема, потому что 64-битная, похоже, не использует искажение имен. На 64-битной компилятор создает символ с именем FreeLibrary и это, конечно, сталкивается с kernel32 API одноименный и отказывается от ссылки, что приводит к следующей ошибке:

Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

kernel32.lib(KERNEL32.dll) : error LNK2005: FreeLibrary already defined in test.o
    Creating library test.lib and object test.exp
test.dll : fatal error LNK1169: one or more multiply defined symbols found

Таким образом, мне интересно, есть ли способ заставить x64 DLL использовать искажение имени как на 32-битной, чтобы моя DLL могла экспортировать символ с именем FreeLibrary без каких-либо столкновений с kernel32?

Или есть другое решение, чтобы обойти эту проблему?

Единственное решение, которое я вижу, это переименовать FreeLibrary к чему-то, что не конфликтует с API-интерфейсами ОС для x64-версий моего приложения, но, конечно, я бы хотел этого избежать, потому что это снижает согласованность API плагинов моего приложения. Если возможно, я бы хотел сохранить FreeLibrary имя для всех платформ и архитектур.

Есть идеи? Я думаю, если бы было возможно на 32-разрядных использовать зарезервированные имена, такие как FreeLibrary тогда в DLL должен быть способ сделать это на 64-битной версии, не так ли? Но я не понимаю, как...

1 ответ

Я бы не пытался убедить компилятор искажать имена функций. Так лежит безумие.

Чтобы уточнить, ваша единственная проблема заключается в дублировании символов при связывании DLL плагинов. Само приложение не должно заботиться о том, как называются функции, потому что оно будет вызывать точки входа плагина через указатели функций, полученные через GetProcAddress,

Предполагая, что плагинам не нужно вызывать API-интерфейсы Windows, реализованные в kernel32.dll, вы можете попробовать опустить kernel32.dll из команды компоновщика. (См. /NODEFAULTLIB вариант.) Если kernel32.dll не является частью ссылки, не должно быть столкновений.

Но это не сработает, потому что /MT в командной строке подразумевается, что вы зависите от библиотеки времени выполнения C, которая, в свою очередь, зависит от некоторых API-интерфейсов kernel32.dll. (Кроме того, вы уверены, что хотите связать плагины со статической библиотекой времени выполнения, а не с версией DLL?)

Таким образом, оставшийся вариант - изменить имя функции. Это должно быть тривиально, так как вы все равно портируете. Вы даже можете использовать препроцессор для взлома имени при компиляции плагинов, чтобы вам не нужно было менять их исходный код:

cl /EHsc /c /DFreeLibrary=Plugin_FreeLibrary /Fotest.o test.c

А потом поменяй GetProcAddress позвоните в приложение, чтобы найти Plugin_FreeLibrary вместо FreeLibraryЯ предполагаю, что это происходит только в одном месте.

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