Почему точка входа в процедуру не может находиться в dll, когда я ее точно вставил?

У меня действительно неопределенная проблема, но я надеюсь, что кто-то может помочь с ней. Я модифицировал проект C++, вчера он еще работал, а сегодня уже нет. Я почти уверен, что ничего не менял, но чтобы быть полностью уверенным, я снова проверил проект из SVN и даже вернулся к предыдущей точке восстановления системы (потому что это рабочий компьютер, он иногда тайно устанавливает обновления и т. ). После успешной компиляции программа может запуститься, но после взаимодействия с ней я получаю следующую ошибку: Точка входа в процедуру ?methodName@className@@UAEXXZ не может быть расположена в библиотеке динамической компоновки libName.dll.

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

По сути, я ничего не знаю о DLL, связывании и т. д., поэтому я был бы очень признателен, если бы у кого-нибудь возникло представление о том, почему функции, которые очень четко определены в проекте, внезапно больше не попадают в DLL. . Я знаю, что это расплывчато, и если потребуется дополнительная информация, я с радостью ее предоставлю. Спасибо!

Обновление: я попробовал предложенные варианты, но все равно не могу. __declspec(dllexport) видимо не используется во всем проекте. Открытие DLL с помощью Dependency Walker показывает пустой верхний правый раздел, а в разделе под ним перечислены функции из сообщения об ошибке. Если я отмечу Undecorate C++ Functions, все будет выглядеть нормально, но если я этого не сделаю, то в сообщении об ошибке появятся странные вопросительные знаки и символы @, а в конце появится разница:

?methodName@className@@UAEXXZ
?methodName@className@@UAEXH@Z

Возможно, проблема в этом, но я понятия не имею, что это значит, что может быть причиной этого и что я могу с этим поделать.


person Jordi    schedule 03.12.2009    source источник
comment
Вы пытались добавить /Wall к параметрам компилятора VC++? Может подскажете...   -  person Romain    schedule 03.12.2009


Ответы (4)


Вы действительно используете __declspec(dllexport)? Я предполагаю, что нет - без этого объявления эта функция не будет экспортирована DLL (или, другими словами, программы, загружающие эту DLL, не будут иметь доступа к функциям без этого объявления).

Кроме того, попробуйте использовать Dependency Walker, чтобы увидеть, какие именно функции доступны в вашей DLL.


Тот факт, что __declspec(dllexport) не используется в объявлениях функций, в порядке вещей — в большинстве случаев он будет использоваться только один раз в одном заголовочном файле, например

#ifdef MAKING_DLL
#define FOO_API __declspec(dllexport)
#else
#define FOO_API
#endif

Так что, если у вас есть #define MAKING_DLL перед этим разделом, все функции, которые объявлены как FOO_API int BakeACake(), будут экспортированы в зависимости от того, был ли определен MAKING_DLL. Возможно, проект ожидал, что MAKING_DLL (или его эквивалент) будет определен в командной строке, в зависимости от типа построенного проекта (что-то вроде /DMAKING_DLL; или вам может даже понадобиться определить FOO_API самостоятельно, например /DFOO_API=__declspec(dllexport).

Пустой верхний правый раздел в Dependency Walker просто означает, что ваша программа не связывается с соответствующим файлом .lib библиотеки DLL. Все в порядке, это просто означает, что вы используете LoadLibrary или LoadLibraryEx для доступа к функциям в DLL.

Другой довольно вероятный сценарий (на основании того факта, что искаженные имена отличаются) заключается в том, что программа была собрана с использованием версии Visual Studio, отличной от версии 2008, которую вы использовали для сборки DLL. В отличие от обычного C, для C++ не существует стандартного бинарного интерфейса, а это означает, что вам придется использовать один и тот же компилятор для сборки программы и библиотеки DLL при использовании классов C++ в библиотеке DLL. Если можете, попробуйте пересобрать программу в VS2008 или попробуйте пересобрать DLL в той же версии VS, в которой была собрана программа.

person Mark Rushakoff    schedule 03.12.2009
comment
Спасибо за Ваш ответ! Я пробовал смотреть на ваши предложения, но я все еще застрял (см. обновление к моему вопросу). Если у вас есть еще предложения, это было бы здорово! - person Jordi; 04.12.2009

Загрузите прохождение зависимостей и откройте свою dll с помощью этого инструмента. Он покажет список экспортированных функций из вашей dll. Проверьте, является ли вышеупомянутый метод частью ожидаемых функций. Если это не так, то это означает, что вы случайно удалили __declspec(dllexport) для одного из классов в этой dll.

person Ponting    schedule 03.12.2009
comment
Ваш ответ, похоже, точно такой же, как и на плакате над вами, но все равно спасибо! Я попробовал предложения, но я все еще застрял (см. обновление к моему вопросу). Буду благодарен за дополнительную помощь! - person Jordi; 04.12.2009
comment
@Jordi: Это первое, что люди сделают, столкнувшись с этой проблемой. Думаю, мы начали печатать вместе, и он закончил раньше меня. - person Ponting; 08.12.2009

Я чувствую себя немного глупо, но я нашел ответ. Приложение (exe), которое я использовал, по-видимому, загружало вторую, другую dll, которая зависела от упомянутой в моем исходном посте. Эта вторая dll все еще ожидала старых функций, и ее также нужно было перекомпилировать с обновленной dll.

Большое спасибо людям, которые пытались мне помочь здесь!

person Jordi    schedule 08.12.2009

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

person Povilas    schedule 18.04.2011