Вот загадка, на которую я не могу найти ответ (здесь, на SO или других сайтах). Я новичок в SO, но я пытаюсь учиться быстро.
Мне нужно изменить имя моей процедуры точки входа dll с
int subCreatePipe()
в
int subCreateNewPipe()
Но запускающая программа умирает, когда я это делаю.
Конкретная ошибка:
«Не удалось найти точку входа в процедуру subCreateNewPipe в библиотеке динамических ссылок myPipe.dll»
Настройки, на которых я работаю:
MBCS
Теперь вот кикер:
int subCreatePipe()
в этом. TestPipe
подпапка проекта «Lib». В TestPipe.cpp у меня есть строка для вызова процедуры:
x = subCreatePipe();
Я компилирую TestPipe.cpp и запускаю выпуск «TestPipe.exe», и он работает отлично.
Находит точку входа в subCreatePipe.
Но мне нужно переименовать процедуру DLL в subCreateNewPipe
придерживаться соглашения об именах, которое я не могу контролировать.
int subCreateNewPipe()
В TestPipe.cpp я изменяю вызов процедуры на:
x = subCreateNewPipe();
Я компилирую TestPipe.cpp и запускаю релиз «TestPipe.exe», и он умирает (с ошибкой, приведенной выше).
Если я вернусь и изменим имя DLL-процедуры на subCreatePipe
, он снова запустится. Если я вернусь и изменить его на subCreateNewPipe
опять умирает. Единственное, что я делаю по-другому, это изменение имени процедуры точки входа.
Итак, мои вопросы:
DLLMain()
хотя я бы просто оставил это пустым? (Это кажется плохой формой.) Несколько других вещей, которые я попробовал (которые все еще дают те же результаты «первого способа работы», но «второго способа не получается»):
Я пытался с помощью __stdcall
int __stdcall subCreatePipe() // works
int __stdcall subCreateNewPipe() // doesn't work
Я пытался с помощью __declspec(dllexport)
ifdef X_EXPORT_FLAG
#define DLL_IMPORT_EXPORT __declspec(dllexport)
else
#define DLL_IMPORT_EXPORT __declspec(dllimport)
endif
X_EXPORT_FLAG int __stdcall subCreatePipe() // works
X_EXPORT_FLAG int __stdcall subCreateNewPipe() // doesn't work
Я также попытался использовать файл .DEF, чтобы определить имя процедуры для компоновщика.
int subCreatePipe() // works
int subCreateNewPipe() // doesn't work
(Во всех примерах я изменяю код TestPipe.cpp для вызова правильного имени процедуры.)
Если вы не можете сказать, я немного обеспокоен попытками выяснить, как заставить это работать.
Сейчас я собираюсь создать новое консольное приложение Win32 для вызова библиотеки DLL (что я должен был сделать 24 часа назад). Однако мне все еще очень любопытно, почему я не могу изменить имя процедуры точки входа. Будем с благодарностью приветствовать любые идеи о том, почему этого нельзя сделать, о лучших методах кодирования или о том, как обойти эту проблему компоновщика.
РЕШЕНИЕ:
В Неуправляемый C ++, библиотеки DLL не удаляются из папки «Release», как в Managed C ++. Вы должны физически перемещать новую DLL в папку «Release» вашей прикладной программы каждый раз, когда вы вносите изменения в свою DLL.
Я узнал, как бороться с обновлением DLL в Удалось C ++, где все, что вам нужно сделать (в папке вашей прикладной программы) — очистить старую подпапку библиотеки DLL и скопировать новую версию измененных DLL в эту пустую подпапку библиотеки. Когда вы «очищаете и перестраиваете» приложение, которое вызывает эти DLL, Удалось VS2010 C ++ удалит старые DLL из папки «Release» и скопирует новые DLL из подпапки библиотеки в папку «Release» приложения. Это хорошо держит вашу DLL в актуальном состоянии.
В Неуправляемый C ++, «Очистить и восстановить» делает не удалите ваши старые DLL из папки «Release» приложения. И это не скопируйте новую DLL из вашей подпапки библиотеки либо. Поэтому, хотя я и думал, что помещаю свои новые DLL в папку, в которой моя программа могла их найти, они не копировались, как в Managed C ++.
Когда Майкл Берр дал мне link /dump /exports myPipe.dll
инструменты, я смог увидеть метку времени DLL и процедуры, которые были доступны. (В моем случае это была первая сборка DLL, в которой была только одна процедура.) Было очевидно, что это старая DLL, а не текущая.
Это объясняет, почему приложение всегда запускалось со старым именем процедуры. Однако при компиляции с новым именем процедуры он выдал ошибку точки входа в процедуру, поскольку приложению удалось найти только старую DLL (в которой новое имя процедуры не существовало).
Еще раз спасибо! 🙂