2010-08-23 2 views
1

Я импортирую C++ DLL в скрипт установки innosetup. Код DLL выглядит следующим образом:Проблема с импортом DLL в Inno-Setup

void __stdcall SetFbParam(char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue){ 
//of no use here and doesn't change anything} 

В InnoSetup, я импортировать его с помощью

procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;); 

external '[email protected]:MyDll.dll stdcall setuponly';

Однако, я всегда получаю сообщение об ошибке выполнения при запуске программы установки, заявив, что он не может импортировать мою dll. Я попробовал это с различными соглашениями о вызовах, но он всегда терпит неудачу. Если это имеет значение, я запускаю Win7 x64 с UAC (после этого установщик запрашивает правку прав и аварий).

Точное сообщение:
Ошибка
Ошибка выполнения (на -1: 0):
Невозможно импортировать
DLL C: \ Users \ Nevod \ AppData \ Local \ Temp \ это-6LOEC.tmp \ MyDll.dll

Там есть DLL.

Спасибо!

+0

Не заставляйте нас угадывать сообщение об ошибке выполнения. –

+0

Точное сообщение: Ошибка Ошибка выполнения (на -1: 0): Невозможно импортировать длл: C: \ Users \ Nevod \ AppData \ Local \ Temp \ есть-6LOEC.tmp \ MyDll.dll dll есть. – nnevod

+0

И функция, которую вы импортируете, также экспортируется на самом деле? – deemok

ответ

5

Is MyDll.dll 32-bit?

Does MyDll.dll зависят от других DLL-файлов в одном и том же каталоге? Если это так, вам нужно указать имя (имена) этих DLL после «MyDll.dll», чтобы убедиться, что они извлечены до MyDll.dll загружен, и вам, вероятно, понадобится опция «loadwithalterdesearchpath». Пример из help:

procedure ADllFunc(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal); 
external '[email protected]:A.dll,B.dll stdcall loadwithalteredsearchpath'; //A.dll depends on B.dll 
3

(я знаю, что это старый, но, возможно, некоторые другие хиты это один тоже)

Скорее всего, имя функции искажаются в DLL C++. У меня была та же проблема, и я смог ее решить, перекомпилировав dll. Короче говоря:

Если вы экспортируете из C++ что-то вроде:

void __stdcall foo() 

вы получите функция называется (Visual Studio):

[email protected]@YGXXZ 

Чтобы предотвратить имя коверкая следует использовать экспорт «C ». Пример (Visual Studio)

extern "C" __declspec(dllexport) void __stdcall foo() 

Однако я обнаружил, что Visual Studio будет продолжать калечить, и вы получите что-то вроде:

[email protected] 

единственного пути я был в состоянии получить чистые имена описано здесь: C++ DLL Export: Decorated/Mangled names

И виновник действительно __stdcall. Если вы удалите это из своей декларации: вы снова получите чистый экспорт, даже без файла DEF. Если вы удалите это из своей декларации:

Вы получите чистый экспорт даже без файла DEF.IMO это должно быть достаточно хорошим, так как вышеприведенный код объявляет экспортированную функцию «C», а соглашение о вызове по умолчанию для C - это stdcall. Однако у меня не было времени и решимости проверить это, поскольку добавление DEF-файла намного проще, чем переход к asm-коду и проверка указателей стека :)

+0

Спасибо, @Ялос решил эту проблему для меня! – yairchu

+0

Ты - спасатель, я никогда бы не догадался, что проблема была решена. – caesay

1

Для того, чтобы использовать DLL в разделе [Code] в InnoSetup, убедитесь, что:

  • DLL находится в 32-битном режиме (даже если установщик построен для 64-битных и работает в 64-разрядном режиме)
  • экспортируемые функции имеют extern "C" __declspec(dllexport) модификатор
  • использовать Cdecl соглашение о вызове, потому что STDCALL искалечил имя (http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx). Конечно, в заявлении импорта InnoSetup можно указать искомое имя. Но проще просто использовать cdecl
+0

* «Использовать конвенцию вызова cdecl, потому что stdcall управляет именем» *, не могли бы вы рассказать об этом, пожалуйста? – TLama

+0

Я не уверен, почему, и у меня не было времени поиграть с ним, но по некоторым причинам DLL, скомпилированная с помощью stdcall, экспортировала имя примерно так: '_function @ 8' при компиляции той же самой DLL, которая просто менялась ** в целом вызывающая конвенция проекта ** в cdecl изменила экспортированное имя на 'function'. Я провел тесты с VS2010. – rkudinov

+0

. Вы встречались так называемое мангание имен, но я не думаю, что это не повод предположить, что вы сделали. Я считаю, что вы можете [остановить VS, чтобы сделать это] (http://stackoverflow.com/q/1467144/960757). – TLama

Смежные вопросы