>
>Calling DLL functions from a C++Builder project 0 p$ f9 b& O" E, S+ h" Y5 X
>Calling DLL functions from a C++Builder project u& n; j: J- C* K3 ^
>You need to gather three ingredients in order to call a DLL function from your C++Builder program: the DLL itself, a header file with function prototypes, and an import library (you could load the library at runtime instead of using an import library, but we will stick to the import library method for simplicity). To call a DLL function, add the import library to your C++Builder project by selecting the Project | Add To Project menu option in C++Builder. Next, insert a #include statement for the DLL header file in the C++ source file that needs to call one of the DLL functions. The last step is to add the code that calls the DLL function. </P>, `1 g% d* o1 K
>Listings A and B contain source code for a DLL that can serve as a test DLL. Notice that the test code implements two different calling conventions (__stdcall and __cdecl). This is for a very good reason. When you try to call a DLL that was compiled with Visual C++, most of your headaches will result from disagreements due to calling conventions. Also notice that one function does not explicitly list the calling convention that it uses. This unknown function will act as a measuring stick for DLL functions that don't list their calling convention. </P>
>//------------------------------------------! X1 y8 }: O, v' v
>#ifdef __cplusplus
>#ifdef _BUILD_DLL_2 Y7 K( U8 u, B) B' o4 w
>FUNCTION int __stdcall StdCallFunction(int Value);
>#ifdef __cplusplus
>. I1 z" R1 X5 Q1 m; O7 q3 l6 x
>#define _BUILD_DLL_
>FUNCTION int __stdcall StdCallFunction(int Value)5 k+ Y/ @* Y( Q1 J% |, v& y
>FUNCTION int __cdecl CdeclFunction(int Value)3 [5 Z6 f& X, c! ]
>FUNCTION int UnknownFunction(int Value)
>To create a test DLL from Listing A and Listing B, open up C++Builder and bring up the Object Repository by selecting the File | New menu option. Select the DLL icon and click the OK button. C++Builder responds by creating a new project with a single source file. That file will contain a DLL entry point function and some include statements. Now select File | New Unit. Save the new unit as DLL.CPP. Cut and paste the text from Listing A and insert it into the header file DLL.H. Then copy the code from Listing B and insert it into DLL.CPP. Make sure that the #define for _BUILD_DLL_ is placed above the include statement for DLL.H. </P>
>Save the project as BCBDLL.BPR. Next, compile the project and take a look at the files produced. C++Builder generates both a DLL and an import library with a .LIB extension. </P>* O) g4 y% w# J
>At this point, you have the three ingredients needed to call a DLL from a C++Builder project: the DLL itself, a header file for function prototypes, and an import library to link with. Now we need a C++Builder project that will try to call the DLL functions. Create a new project in C++Builder and save it to your hard drive. Copy the DLL, the import library, and the DLL.H header file from DLL project to this new project. Select the Project | Add To Project menu option and add the LIB file to the project. Next, add a #include statement in the main unit that includes DLL.H. Finally, add code that calls the DLL functions. Listing C shows code that calls each the DLL functions from Listing A and B. </P>
>//------------------------------------------
>#include "MAINFORM.h"
>The problem with Visual C++ DLLs
>The two products also disagree on linker naming conventions. This turns out to be the primary hurdle when trying to call a Visual C++ DLL from C++Builder. Every function in a DLL or OBJ has a linker name. The linker uses the linker name to resolve functions that were protoyped during compile time. The linker will generate an unresolved external error if it can't find a function with a linker name that it thinks is needed by the program. </P>
>With regard to linker function names, Borland and Microsoft disagree on these points: </P>
>1- Visual C++ sometimes decorates exported __stdcall functions. ) `4 u3 m! H; \% b
>So why is this such a big deal? Take disagreement #1 regarding the __stdcall calling convention. If you create a DLL with Visual C++ that contains a __stdcall function called MyFunction(), Visual C++ will give the function a linker name that looks like <a href="mailt_MyFunction@4" target="_blank" >_MyFunction@4</A>. When the Borland linker tries to resolve calls made to this function, it expects to find a function with the name MyFunction. Since the import library for the Visual C++ DLL doesn't contain a function called MyFunction, the Borland linker reports an unresolved external, which means it couldn't find the function. </P>/ w7 m# T$ m, T" J' c5 L- ]
>Your attack strategy for overcoming these three problems will depend on how the Visual C++ DLL was compiled. I have broken the process into four steps. </P>5 K1 n0 G1 ~/ |, p; [
>Step 1: Identify calling conventions used by the Visual C++ DLL ( a9 U" X# V1 V8 R& p- z* y
> __declspec(dllimport) void CALLING_CONVENTION MyFunction(int nArg);</P>+ H4 M d! H$ v9 W* z! B
>CALLING_CONVENTION should be __stdcall or __cdecl (see Listing A for concrete examples). In many cases, the calling convention won't be specified, in which case it defaults to __cdecl. </P>9 h. i5 ~" C! G& Y" r1 V! t# u! B
>Step 2: Examine the linker names in the DLL ; }( r! A: S7 p; y" U4 Z| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) | Powered by Discuz! X2.5 |