Как в MSVC из .DLL сделать .LIB, чтобы юзать ф-ии из этой DLL ?
(через LoadLibrary/GetProcAddress не охота)
Например, мне нужна ф-я WsControl из wsock32.dll
Объявлена она у меня так:
extern "C" int WINAPI WsControl(DWORD protocol,
DWORD action, LPVOID pRequestInfo,
LPDWORD pcbRequestInfoLen,
LPVOID pResponseInfo,
LPDWORD pcbResponseInfoLen);
Но при линковке с моей lib выдается ошибка:
error LNK2001: unresolved external symbol _WsControl@24
Так как ф-я объявлена с модификатором __stdcall, линкер ищет искаженное имя _WsControl@24, а в lib оно не искаженное - просто WsControl.
Если ф-ю объявить как __cdecl или написать в wsock32.def искаженное имя:
EXPORTS
WsControl@24
то программа cлинкуется, но по понятным причинам не будет работать.
Очевидно, что можно сделать свою wsock32.dll, объявить в ней WsControl, и при ее компиляции создастся нормальный lib.
Но неужели в MSVC нет простого способа, чтобы из DLL сразу сделать LIB?
В BC++ например это делается одной командой:
implib wsock.llb wsock32.dll
> Как в MSVC из .DLL сделать .LIB, чтобы юзать ф-ии из этой > DLL ? > (через LoadLibrary/GetProcAddress не охота) > Например, мне нужна ф-я WsControl из wsock32.dll > > Объявлена она у меня так: > extern "C" int WINAPI WsControl(DWORD protocol, > DWORD action, LPVOID pRequestInfo, > LPDWORD pcbRequestInfoLen, > LPVOID pResponseInfo, > LPDWORD pcbResponseInfoLen); > > Cоздал файл wsock32.def следующего содержания: > ;--- > LIBRARY WSOCK32 > EXPORTS > WsControl > ;--- > > и сделал свою либу командой: > lib /def:wsock32.def Na skol'ko ya znayu vsyakakashkaimenno v etom.
tebe ne stoit sozdavat' wsock32.def. Pri sozdanii etogo file-a, tebe obyazatel'no nado vyzyvat' LoadLibrary, no sleduet delat' po drugomu :
__declspec(export) ... i prochaya fignya (sejchas v sintaksise ne uveren :-))) ). eto tebe sgenerit wsock32.lib file. nu a potom vse kak obychno :-)
> > Но при линковке с моей lib выдается ошибка: > error LNK2001: unresolved external symbol _WsControl@24 > Так как ф-я объявлена с модификатором __stdcall, линкер > ищет искаженное имя _WsControl@24, а в lib оно не > искаженное - просто WsControl. > Если ф-ю объявить как __cdecl или написать в wsock32.def > искаженное имя: > EXPORTS > WsControl@24 > то программа cлинкуется, но по понятным причинам не будет > работать. > > Очевидно, что можно сделать свою wsock32.dll, объявить в > ней WsControl, и при ее компиляции создастся нормальный > lib. > > Но неужели в MSVC нет простого способа, чтобы из DLL сразу > сделать LIB? > В BC++ например это делается одной командой: > implib wsock.llb wsock32.dll
> > и сделал свою либу командой: > > lib /def:wsock32.def > Na skol'ko ya znayu vsyakakashkaimenno v etom. > > tebe ne stoit sozdavat' wsock32.def. Pri sozdanii etogo > file-a, tebe obyazatel'no nado vyzyvat' LoadLibrary, no > sleduet delat' po drugomu : > __declspec(export) ... i prochaya fignya (sejchas v > sintaksise ne uveren :-))) ). eto tebe sgenerit wsock32.lib > file. nu a potom vse kak obychno :-)
Это-то понятно, я же писал:
> > > > Очевидно, что можно сделать свою wsock32.dll, объявить в > > ней WsControl, и при ее компиляции создастся >> нормальный lib.
Понятное дело, что можно создать такую пустышку wsock32.cpp:
И при ее компиляции сгенерится wsock32.lib.
Но все равно без DEF-файла тут не обойтись, пототому что при экспорте с помощью __declspec(dllexport) генерится mangled name (а в виндусовом wsock32.dll оно WsControl - не mangled)
Зато экспорт через DEF-файл - не искажает имен (или можно заставить __declspec(dllexport) не декорировать имена ?)
Вот что показывает dumpbin для этих двух случаев:
Экспорт ф-ии WsControl() с помощью __declspec(dllexport):
// compiled with:
// cl wsock32.cpp /link /dll /out:wsock32.dll /noentry
DLL name : wsock32.dll
Symbol name : _WsControl@24
Name type : name <-------------- !!!!!
Hint : 0
Name : _WsControl@24 <----- !!!!!
DLL name : wsock32.dll
Symbol name : _WsControl@24
Name type : undecorate <-------- !!!!!
Hint : 0
Name : WsControl <--------- !!!!!
Но меня интереовал более легкий способ создания .LIB файлов из имеющихся .DLL
(чтобы не создавать wsock32.cpp)
Я нашел вот такой способ:
; --- wsock32.def
LIBRARY WSOCK32
EXPORTS
WsControl@24 @1001
; ---
lib /def:wsock32.def
Создается wsock32.lib, но при линковке с ним в получившемся экзешнике WsControl() импортируется только по ординалу 1001.
А если я хочу импортировать WsControl по имени, то надо создавать .lib обычным способом (городить огород с wsock32.cpp и wsock32.def)
Как у M$ все запущено :-( У Борланда это одной командой делается...
А может я зря M$ ругаю и еще какие-нибудь способы есть?
И еще вопрос: как экспортировать ф-ю из DLLтолькопо ординалу?
> > > и сделал свою либу командой: > > > lib /def:wsock32.def > > Na skol'ko ya znayu vsyakakashkaimenno v etom. > > > > tebe ne stoit sozdavat' wsock32.def. Pri sozdanii > etogo > > file-a, tebe obyazatel'no nado vyzyvat' LoadLibrary, > no > > sleduet delat' po drugomu : > > __declspec(export) ... i prochaya fignya (sejchas v > > sintaksise ne uveren :-))) ). eto tebe sgenerit > wsock32.lib > > file. nu a potom vse kak obychno :-) > > Это-то понятно, я же писал: > > > > > > Очевидно, что можно сделать свою wsock32.dll, > объявить в > > > ней WsControl, и при ее компиляции создастся > >> нормальный lib. > > Понятное дело, что можно создать такую пустышку > wsock32.cpp: > > // ------- wsock32.cpp > #include <windows.h> > > extern "C" __declspec(dllexport) > int WINAPI WsControl(DWORD protocol, > DWORD action, LPVOID pRequestInfo, > LPDWORD pcbRequestInfoLen, > LPVOID pResponseInfo, > LPDWORD pcbResponseInfoLen) > { > return 0; > } > // ------- EOF > > И при ее компиляции сгенерится wsock32.lib. > Но все равно без DEF-файла тут не обойтись, пототому что > при экспорте с помощью __declspec(dllexport) генерится > mangled name (а в виндусовом wsock32.dll оно WsControl - не > mangled) > Зато экспорт через DEF-файл - не искажает имен (или можно > заставить __declspec(dllexport) не декорировать имена ?) > Вот что показывает dumpbin для этих двух случаев: > > Экспорт ф-ии WsControl() с помощью __declspec(dllexport): > // compiled with: > // cl wsock32.cpp /link /dll /out:wsock32.dll /noentry > > DLL name : wsock32.dll > Symbol name : _WsControl@24 > Name type : name <-------------- !!!!! > Hint : 0 > Name : _WsControl@24 <----- !!!!! > > Экспорт ф-ии WsControl() через DEF-файл: > // compiled with: > // cl wsock32.cpp /link /dll /out:wsock32.dll /noentry > /def:wsock32.def > // OR > // cl wsock32.cpp /link /dll /out:wsock32.dll /noentry > /export:WsControl > > DLL name : wsock32.dll > Symbol name : _WsControl@24 > Name type : undecorate <-------- !!!!! > Hint : 0 > Name : WsControl <--------- !!!!! > > > Но меня интереовал более легкий способ создания .LIB файлов > из имеющихся .DLL > (чтобы не создавать wsock32.cpp) > Я нашел вот такой способ: > ; --- wsock32.def > LIBRARY WSOCK32 > EXPORTS > WsControl@24 @1001 > ; --- > lib /def:wsock32.def > Создается wsock32.lib, но при линковке с ним в получившемся > экзешнике WsControl() импортируется только по ординалу > 1001. > А если я хочу импортировать WsControl по имени, то надо > создавать .lib обычным способом (городить огород с > wsock32.cpp и wsock32.def) > Как у M$ все запущено :-( У Борланда это одной командой > делается... > А может я зря M$ ругаю и еще какие-нибудь способы есть? > > И еще вопрос: как экспортировать ф-ю из DLLтолькопо > ординалу?
ya ispol'zoval DLL tak :
esli deklariju - __declspec(dllexport) , to .DEF file ne igraet roli. t.e. mne dostatochno prosto vkljuchit' v project "wsock32.lib", i on avtomatom podymet "wsock32.dll". dal'she menya nichego ne interesuet.
kstati, esli dazhe ispol'zuju .DEF file, to vse ravno v VC++ rabotaet.
Bylo dazhe takoe :
pisal .DLL on ne podymalsya v Oracle, t.k. ya generil .LIB file. kogda zapreshal generit' .LIB, to ljubaja programma podymala ego.
a chtoby ispol'zovat' f-ii v tvoem .EXE, nuzhno vkljuchat' f-ii takim obrazom :
__declspec(dllimport) :
kstati, ya postoyanno putayu gde nado dllexport , a gde dllimport :-))) tak chto esli chto ne poluchitsya, to pomenyaj ix mestami :-)))))
dlja etogo konechno luchshe napisat' MACROS raz i navsegda, naprimer :
#ifPRODUCE_DLL #define FUNCTION __declspec(dllexport)
#else
#define FUNCTION __declspec(dllimport)
#endif
dalee uzhe ponyatno :
FUNCTION int WINAPI SomeShit();
esli .LIB generitsya, to problem u tebyanikakixne dolzhno byt'. i GetProcAddress() tebe voobshe ne nuzhen budet
> > a chtoby ispol'zovat' f-ii v tvoem .EXE, nuzhno > vkljuchat' > > f-ii takim obrazom : > > __declspec(dllimport) : > > > > extern "C" __declspec(dllimport) > > int WINAPI WsControl(DWORD protocol, > > DWORD action, LPVOID pRequestInfo, > > LPDWORD pcbRequestInfoLen, > > LPVOID pResponseInfo, > > LPDWORD pcbResponseInfoLen) > > { > > } > > > #ifPRODUCE_DLL > > #define FUNCTION __declspec(dllexport) > > #else > > #define FUNCTION __declspec(dllimport) > > #endif > > > > dalee uzhe ponyatno : > > FUNCTION int WINAPI SomeShit(); > > в макросе ты забыл extern"C" > а это основное почему будут или не будут кривыми имена > > в h-файле удобно сделать так (как обычно и делают) : > > #ifdef __cplusplus > extern"C" > { > #endif > > // содержимое файла > > #ifdef __cplusplus > } > #endif >
Даже если поставить extern "C", а ф-я объявлена как _stdcall, то имя у нее все равно будет кривое (напр. WsControl@24, т.е. добавляется подчеркивание и кол-во байт на стеке). А с _cdecl все нормально. Поэтому если хотим экспортировать не кривое имя, надо пользоваться .DEF-файлом или ключом /export в командной строке линкера.
> poslushaj, ya tak i ne ponyal, na fig tebe "pryamye" imena > ???? > esli ty vsju etu fignju bidesh' v C++ ispol'zovat', to > kakogo figa bespokoitsya ???
Что же тут непонятного? :-)
Я использую ф-ю WsControl из wsock32.dll. Она нелокументированная, и в стандартном wsock32.lib ее нет. Через GetProcAddress() ее доставать неохота, хочеца создать свой либ с этой функцией. А у нее имя прямое :-))
> Я использую ф-ю WsControl из wsock32.dll. Она > нелокументированная, и в стандартном wsock32.lib ее нет. > Через GetProcAddress() ее доставать неохота, хочеца > создать свой либ с этой функцией. А у нее имя прямое :-))
oh nu da ... chto to ya tormozhu :-)))
interestnaya fignja ...
tut vot drugoj variant, tozhe pravda krivoj :-)))) no esli tebja vozvrashaemoe znachenie ne volnuet, to mozhet stoit poprobovat' takim makarom, ili zhe prosto napishi svoju f-uju, naprimer MyWsControl ...
po moemu prosto naprosto net varianta bez GetProcAddress dokopatsya do f-ii. v krajnem sluchae poprobuj cherez
__decspec(dllexport) - mozhet rebyata iz MS sdelali dobroe delo, ostavili f-iju v LIB-e :-)))
da i na fig, zrya poprostu vremya teryat' - vse genial'noe dolzhno byt' prosto. usaj tradicionnymi metodami i vse :-)))