2008-11-12 12 views
7

Mam dwie biblioteki DLL, do których muszę uzyskać dostęp w tym samym pliku wykonywalnym. Mam pliki nagłówkowe i pliki .LIB dla obu bibliotek. Niestety, podzbiór funkcji, które muszę mieć dostęp, ma dokładnie takie same nazwy. Najlepszym rozwiązaniem, jakie udało mi się wymyślić do tej pory, jest użycie LoadLibrary do załadowania jednej z bibliotek DLL i jawne wywołanie jej metod za pomocą GetProcAddress. Czy istnieje sposób dla mnie, aby niejawnie załadować obie biblioteki i jakoś dać kompilatorowi wskazówkę, że w jednym przypadku chcę wywołać OpenApi w DLL A, a w innym przypadku chcę wywołać OpenApi w DLL B?Wywołanie dwóch funkcji o tej samej nazwie z dwóch różnych bibliotek DLL C

Opracowuję swój plik wykonywalny w C++ przy użyciu Visual Studio 2008 i odpowiedniej biblioteki uruchomieniowej C (msvcr90.dll).

[Edytuj]

Commenter Ilya pyta poniżej tego, co mi się nie podoba o rozwiązanie GetProcAddress. Nie podoba mi się to z dwóch powodów:

  1. Sprawia, że ​​kod jest bardziej złożony. Jedna linia kodu do wywołania funkcji zostaje zastąpiona trzema liniami kodu, jedna do zdefiniowania sygnatury funkcji, jedna do wywołania GetProcAddress, a druga do wywołania funkcji.
  2. Jest bardziej podatna na błędy czasu wykonywania. Jeśli źle wypiszesz nazwę funkcji lub zepsuję podpis, nie widzę błędu do czasu wykonania. Powiedzmy, że postanowiłem zintegrować nową wersję biblioteki dll i jedna z nazw metod została zmieniona, skompiluje się dobrze i nie będzie miała problemu aż do faktycznego połączenia z GetProcAddress, które może nawet zostać pominięte w przepustce testowej.

Odpowiedz

4

Kiedyś można było zmienić nazwę zaimportowanego symbolu za pomocą pliku link .def. Prawdopodobnie nadal możesz, ale od dawna pliki .def były szeroko stosowane, trudno jest zlokalizować dokumentację.

Aktualna dokumentacja MSDN zawiera dyrektywę IMPORTS jako "zastrzeżone słowo kluczowe". Nie jestem pewien, czy oznacza to, że usunęli funkcjonalność, czy po prostu nie chcą już jej obsługiwać.

Oto na stronie opisującej dyrektywę Import:

http://www.digitalmars.com/ctg/ctgDefFiles.html#imports

Inne alternatywy kludgy są:

  1. tworzyć funkcje otoczka do sprzecznych API. Te funkcje mogą wykonywać taniec LoadLibrary()/GetProcAddress(). Wszystkie pozostałe funkcje, które nie są w konflikcie, mogą być niejawnie połączone tak jak zwykle. W rzeczywistości to rozwiązanie jest prawdopodobnie najmniejszą z trzech odpowiedzi.

  2. utworzyć 2 otoki DLL, tak aby każda z nich łączyła się tylko z jedną lub drugą biblioteką ze sprzecznymi nazwami. Używaj różnych nazw w opakowujących bibliotekach DLL, które po prostu trafiają do prawdziwych bibliotek. Uwaga: biblioteki opakowujące nie muszą owijać wszystkich interfejsów API - wystarczy je zawinąć.

1

Możliwe jest tworzenie nowych plików biblioteki importu, które zmieniają nazwy tych funkcji, a następnie niejawnie łączą się z obydwoma modułami DLL za pomocą tych nowych bibliotek importowania. Oto artykuł bazy wiedzy Microsoft Knowledge Base opisujący proces: How To Create 32-bit Import Libraries Without .OBJs or Source.

1

Udało mi się dotrzeć do alternatywnej metody Mike'a B. # 2 (lub # 3, jeśli zliczysz oryginalną sugestię) po tym, jak włożyłem trochę więcej uwagi w tę sprawę.

To jest mój ulubiony z trzech dla mojego konkretnego przypadku, ponieważ wydaje się wymagać najmniejszej ilości pracy i może być najbardziej oczywistym do rozszyfrowania dla kogoś nowego patrząc na kod. Wierzę, że mogę po prostu wykonaj następujące kroki i być gotowy do jazdy:

  1. stosowanie niektórych regularne magia ekspresja i znajdź/zamień, aby włączyć pliki nagłówkowe z wywołuje funkcję, że mam w pliku nagłówkowym obwolutę oraz pliku wdrażania wrapper . (gdzie każda metoda w opakowaniu dll jest różnicowana przez jakiś wspólny nowy element do nazwy, oszczędzając mi czasu na rozwiązywanie konfliktów) Więc FunctionCall() staje się WrapperOneFunctionCall() i WrapperTwoFunctionCall() w każdej odpowiedniej dll opakowania.
  2. połączenie dll opakowania do odpowiedniej biblioteki dll.
  3. połączyć mój plik wykonywalny z bibliotekami DLL otoki, usunąć łącza do bibliotek podstawowych, ale nadal zawierać definicje stałej, enum i struct, które nie muszą być usuwane z podstawowej biblioteki dll (ponieważ moje funkcje opakowania nadal mają ten sam parametr typy)

Jeśli ktoś nadal czyta ten wątek, moje następne pytanie brzmi: "Czy coś jest nie tak z tym rozwiązaniem?".

Dziękuję osobom odpowiadającym za ich pomoc.

+0

Ponieważ jest to C++, można również rozważyć użycie przestrzeni nazw w celu rozróżnienia tych dwóch funkcji, zamiast mieszania nazw funkcji w sposób specjalny, który należy wyjaśnić dalej. Wadą jest to, że nie działa to dla wywołujących język C. – orcmid

+0

Znajduję Twoją oryginalną propozycję za pomocą LoadLibrary i GetProcAddress jako najbardziej logiczne i w rzeczywistości najłatwiejsze do wdrożenia. Czy możesz wyjaśnić, dlaczego masz problem z tym podejściem i szukasz alternatywy? – Ilya