Доброе время суток всем. Имеется библитека asterisk.dll в которой только одна функция asterisk_call(соглашение вызова __stdcall). Ф-ция производит вызов номера посредством AMI интерфейса и связывает канал с определенным контекстом/экстеном/приоритетом. Пытаюсь импортировать эту ф-цию в программку на C++, используя .lib и .def файлы. Но ничего не выходит. Собственно, проблема не в конкретной dll или ф-ции. Нужно как-то отменить декорирование имен в Visual C++ или объяснить линковщику с каким именем в библиотеке связано импортируемое имя ф-ции. asterisk.def: LIBRARY "asterisk.dll" EXPORTS asterisk_call asterisk_call@44 = asterisk_call ?asterisk_call@@YGXPADG00000GEKK@Z = asterisk_call C:>lib.exe /DEF:asterisk.def /MACHINE:X86 main.cpp: #include <iostream> #include <windows.h> #pragma comment(lib,"asterisk.lib") extern "C" __declspec(dllimport) VOID WINAPI asterisk_call(PCHAR,WORD,PCHAR,PCHAR,PCHAR,PCHAR,PCHAR,WORD,BYTE,DWORD,DWORD); void main(void) { std::cout<<"Exit..."<<std::endl; asterisk_call("",0,"","","","","",0,0,0,0); ExitProcess(0); } Если это скомпилировать и попробовать запустить, то система скажет "Точка входа в процедуру asterisk_call@44 не найдена в библиотеке DLL asterisk.dll". Это и понятно, что там этой функции нет. Если использовать __cdecl, то все будет хорошо, за исключением проблем со стеком(что вполне логично) и вылетом по эксцепшену. Так же всё будет хорошо и даже работать, если в .def файл добавить ординал ф-ции, тогда вызов будет идти через него. Использовать явное LoadLibrary/GetProcAddress не хочется. Хочется, чтобы библитека с ф-цией светились в импорте программы. В гугле/на MSDN ничего не нашел, хотя вопрос волнует многих, например http://stackoverflow.com/questions/2393178/creating-an-msvc-import-library-from-a-dll-that-uses-stdcall Под конец, вопрос можно сформулировать: каким образом компилятор от MS правильно линкует следующую ф-цию WINBASEAPI DECLSPEC_NORETURN VOID WINAPI ExitProcess( IN UINT uExitCode ); // extern "C" __declspec(dllimport) __declspec(noreturn) VOID __stdcall ExitProcess(IN UINT uExitCode); если из kernel32.lib тот же _ExitProcess@4 в импорте программы принимает правильный вид ExitProcess(а не ExitProcess@4)? Подозреваю, что это или какой-то pragma делается, или __declspec, или где-то лежат настройки для линковки этих системных либ.
m0r1arty о чём вообще речь? о http://www.asterisk.org/ ? я не платный саппорт, если о ссыле выше, то у них свой форум
wsd, библиотека как пример. точно так же можно использовать любую ф-цию из kernel32.dll при этом попробовать создать .lib из .def файла и залинковать всё это. вопрос в том, чтобы при соглашении __stdcall линкер прописал в импорт ExitProcess(например, или касаемо моего пример asterisk_call, а не ExitProcess@4 или asterisk_call@44, соотвественно).
Могу дать тулзу которая отрезает _ и @. ^) А вообще делаем библиотеку, прописываем секцию экспорта с нужным именем и вуаля, 5 минут работы.
Booster, спасибо, конечно, но тулзы не надо Я хочу узнать почему и как из kernel32.lib в конечный exe`шник попадают API с правильными именами Узнать и повторить
m0r1arty Ну так сделайте проект lib, сделайте def файл в котором будет прописана экспортируемая функция asterisk_call и используйте полученную библиотеку-переходник для подключения оригинальной либы.
m0r1arty точно с этим же сталкивался в итоге как я решил создаете проект dll в нем просто прописываете эксопртируемые функции собираете берете оттуда нужный lib и используете в своем проекте все правильно собирается работает а вот если делать как вы то у меня тоже были такие же проблемы как у вас //ps мне бы тоже было интересно узнать как готовить либы для системных дллок без создания своего проекта dll в нем для нужных апишек прописывания экспорта и изымания оттуда готового lib файла и подключения его к своему проекту
Спасибо за ответы. Я так понял, что это(какое название ф-ции будет в импорте) зависит от содержимого .lib файла. Следовательно то, что выплевывает на выходе lib.exe не подходит. Видимо надо или "правильную" lib.exe искать или пристальней смотреть на параметры/настройки текущей. На сколько я знаю формат DEF такого не поддерживает.
Только что попробовал lib.exe - всё нормально работает. Код (Text): LIBRARY "asterisk.dll" EXPORTS asterisk_call
Booster Странно. У вас не возникло при линковке ошибки "error LNK2019: unresolved external symbol __imp__asterisk_call@44 referenced in function _main"? Код изменяли? lib.exe из какой студии? Можете asterisk.lib выложить?
Ошибок никаких нету. lib.exe пробовал из 2005 и 2010 студий. В def добавил дополнительную функцию для чистоты эксперимента.
Никаких параметров и @ в def писать не надо. В проге использующей dll примерно так: extern "C" int asterisk_call(int);
да, но тогда будет срывать стек из-за __cdecl(по умолчанию). да и ф-цию не вызвать без совпадения кол-ва и типов аргументов. у меня VS2010 по прежнему не находит зависимости.
Получилось Всем кому интересно(osox) объясняю как: 1. формируем INC файл asterisk.inc Код (Text): asterisk_call PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD 44 байта(_asterisk_call@44) - это 11 DWORD 2. берем из пакета MASM32 утилиту INC2L.EXE 3. скармливаем наш инклюд c:\masm32\include\INC2L.EXE asterisk.inc 4. на выходе правильный готовый .lib файл Еще раз всем спасибо.
Апну Кстати если polib.exe скормить например такой def: LIBRARY user32 EXPORTS _MessageBoxA@16 То, если потом использовать полученную lib, в импорт экзешника пишется чистое название MessageBoxA без "_" и @n. И все работает прекрасно. В lib какой то флаг видимо выставляется - в каком виде в импорт писать название функции: с декорацией или без.