VBStreets конференция

Целият вкус на програмирането!

  • Списък на форумитеДруги езици за програмиранеДруги езициC/C++
  • Променете размера на шрифта
  • ЧЗВ
  • вход

#import TLB

#import TLB

добър ден.
Имаше въпрос относно директивата #import

Има някои dll без източници и има tlb, генериран с помощта на MIDL от
idl файлът има нещо подобно:
Код: Изберете всички
[uuid (90000000-4000-4000-8000-0c0000000000)]
библиотека twix
[dllname ("twix.dll")]
модул двадесет
[запис („TWInit“)]
дълъг __stdcall TWInit ();
//.
>;
>;

Използвах това в BASIC, свързвайки tlb референцията в препратките и извиквайки функцията TWInit без колебание.
И сега исках да създам същата връзка с dll в проекта c++.
Код: Изберете всички #import "twix.tlb"
int main (int argc, _TCHAR * argv [])
дълъг b = twix: TWInit ();

връщане 0;
>

Като резултат:
грешка LNK2019: неразрешен външен символ "дълъг __stdcall twix: TWInit (. посочен във функция _DllMain
Е, разбира се, има прототип на функцията, няма изпълнение.
Всъщност въпросът е, защо тогава се нуждаете от директивата #import TLB, ако все пак трябва да се свързвате динамично:
Код: Изберете всички typedef long (__ stdcall * PTR) ();
PTR pFnc = (PTR) GetProcAddress (GetModuleHandleA ("twix"), "TWInit"));
(pFnc) ();

Или не взех предвид нещо и всичко е по-просто?

Re: #import TLB

Директивата е необходима за импортиране на прототипи на функции от TLB.
Функционалните прототипи са необходими на компилатора - използвайки прототипи, компилаторът проверява коректността на повикването (съвпадение на броя и типовете предадени параметри, съвпадение на типа на връщане), а също така използва информация за конвенцията (stdcall/cdecl// fastcall/thiscall), за да генерира правилния машинен код за разговора.

Но компилаторът няма внедряване на функция под ръка, така че генерира призив към външен обект. Файлът obj, създаден от компилатора, просто съхранява информация за всички повиквания към външни обекти. Дори тези външни същества да не съществуват изобщо в природата.

Нещата са съвсем различни, когато куп obj-файлове (генерирани от компилатора) се изпращат към входа на линкера. Линкерът трябва да направи съпоставяне между всички обекти, така че да не останат нерешени външни обекти. В този случай външният обект остава, което е причината за проблема.

Въпросът е, че логиката на компилатора не е обвързана с конкретна система. Нито C/C ++ има средства да маркира функция като импортирана от DLL, нито компилаторът C/C ++ може и не трябва да може да генерира специфична за PE формат таблица за импортиране.

За да се реши този проблем, има така наречените "библиотеки за импортиране". Това са малки статични библиотеки (lib файлове), които съдържат адаптерите, необходими за импортиране на функции от DLL файлове. Човек трябва само да приплъзне съответния import-lib-ku към линкера и външният символ ще престане да бъде неразрешен. Той ще се разреши и съответният елемент ще се появи в таблицата за импортиране, която е необходима за импортиране на функцията TWinit от вашата DLL.

Като цяло, накратко: за да използвате някои DLL от програма на C ++, трябва нещо:

  1. h-файлове, съдържащи прототипи на необходимите функции - необходими на компилатора
  2. lib файлове, съдържащи импортиране thunk - необходими на линкера

Идеята на директивата #importlib е да замени h-файловете с един tlb-файл. h-файловете така или иначе са необходими на компилатора, но директивата #importlib ви позволява да генерирате h-файлове автоматично въз основа на TLB. Директивата се справя с тази задача с гръм и трясък.

Но това не замества необходимостта от lib файлове. lib-файловете са абсолютно винаги необходими: няма значение дали е системна библиотека или някаква произволна. Когато компилираме DLL, няма значение дали компилираме от под VB6 или от под C ++ - lib-файл и exp-файл за тази DLL винаги се генерират автоматично. Те са необходими точно за този случай.

По принцип трябва да намерите този lib файл за вашата библиотека. Няма как без него.

Друго нещо е, че информацията в него е толкова тривиална, че дори ако оригиналният lib-файл не може да бъде намерен, той може да бъде генериран от нулата - източниците на оригиналната библиотека изобщо не се изискват за това.

Прочетете още това, за да изясните неразбирането на същността на момента.