C Builder Engineering uses Visual C DLL - Part 1: C Function Translating: The first reading this article is in October 2001, helping me solve a little problem. I am embarrassed to translate, because the English level is too bad. I have recently found a number of netizens to call Visual C DLL in Ask the C Builder engineering, maybe it is much more than before using C Builder. So I will take my heart, isn't it the brick? "Throwing the jade", I hope it can give you a little busy, and also welcome the mistakes in the translation. Shadowstar 2003-6-3 shadowstar's home: http://shadowstar.126.com/ Source: http://www.bcbdev.com/articles/vcdll.htm It is likely to have a day your boss ask you if you can use C Builder Create a GUI that calls the existing 32-bit DLL compiled with Microsoft Visual C . Often, the source code of the original DLL will not provide you, perhaps because of the DLL from third-party supplier, or may be 22-year-old intern accidentally deleted / dll / src directory from the network. Give you a DLL and header file, this article demonstrates how to call this DLL in your C Builder engineering.
Problem in the C Builder Engineering Problem Band Step 1: Identify the call habits used in Visual C DLL Step 2: Check the connection name in the DLL: Generate for Visual C DLL Introduction, step 4: Adding the introduction library to your engineering Conclusion In the C Builder Engineering call DLL function calls Visual C DLL to the C Builder programmer some unique challenges. Review how to call a C Builder created before we try to resolve the DLL of the Visual C , it may be helpful. Calling the DLL created by C Builder is much less than Visual C . In order to call the DLL in your C Builder engineering, you need three elements: the DLL itself, the header file with function prototype, and the introduction library (you can load the DLL at runtime, not the introduction library, but For the sake of simplicity, we do it according to the introduction of the library). Call the DLL function, first add the introduction library to your C Builder engineering by selecting the menu Project | Add to Project; secondly, insert the #include declaration for the DLL header file in the C source file that needs to call the DLL function. Finally, add the code that calls the DLL function. Program List A and B include source code for testing DLL. Note that the test code achieves two different call habits (__stdcall, and __cdecl). This help is a sufficient reason. When you try to call a DLL compiled with Visual C , most of the things that make your headache are generated by handling different call habits. Also pay attention to a point, there is a function, it does not explicitly list the call habits used. This unknown function is an identification of a DLL function that does not list the habit. // ------------------------------------------ // Listing A: DLL .H
#ifdef __cplusplus
Extern "C" {
#ENDIF
#ifdef _build_dll_
#define function __declspec (dllexport)
#ELSE
#define function __declspec (dllimport)
#ENDIF
Function int __stdcall stdcallfunction (INT VALUE);
Function INT __CDECL CDECLFunction (INT VALUE)
Function int unknownfunction (int value);
#ifdef __cplusplus
}
#ENDIF
// ------------------------------------------
// Listing B: DLL.c
#define _BUILD_DLL_
#include "dll.h"
Function Int __stdcall stdcallfunction (int value)
{
Return Value 1;
}
Function int __cdecl cdeclfunction (int value)
{
Return Value 2;
}
Function Int unknownFunction (int value)
{
Return Value;
}
Create a test DLL from List A and B, open C Builder, and select Menu File | NEW to call up Object Repository. Select the DLL icon and click the OK button. C Builder creates a new project with a source file. This file contains a DLL entry function and some include declarations. Now select File | New Unit. Save the new unit is DLL.cpp. Paste the text insertion of the header file DLL.h from the list A copy. Copy code from the list B and insert it into DLL.cpp. Determine #define _build_dll_tamer on the #include "dll.h" declaration. The preservation project is BCBDLL.BPR. Next, compile the project to see the generated file. C Builder generates a DLL and an introduction library with .lib as the extension. At this time, you have three elements you need to call the DLL in C Builder: DLL itself, with a header file with a function prototype, an introduction library for connection. Now we need a C Builder project used to call the DLL function. Create a new project in C Builder and save it on your hard drive. Copy the DLL from the DLL engineering directory, import library, dll.h header to new directories. Second, add a #include declaration in the main unit, including dll.h. Finally, add the code that calls the DLL function. Listing C lists the code that calls each function in the DLL generated by List A and B. // ------------------------------------------
// listing c: mainform.cpp - DLLTEST Program
#include
#pragma HDRSTOP
#include "mainform.h"
#include "dll.h"
/ / -------------------------------------------------------------------------------------------- ---------
#pragma resource "* .dfm"
TFORM1 * FORM1;
/ / -------------------------------------------------------------------------------------------- ---------
__fastcall tform1 :: tform1 (tComponent * Owner)
: TFORM (OWNER)
{
}
/ / -------------------------------------------------------------------------------------------- ---------
Void __fastcall tform1 :: button1click (Tobject * Sender)
{
INT value = start (edit1-> text);
Int results = stdcallfunction (value);
Resultlabel-> Caption = INTOSTR (Result);
}
/ / -------------------------------------------------------------------------------------------- ---------
Void __fastcall tform1 :: button2click (Tobject * Sender)
{
INT value = start (edit1-> text);
Int results = cdeclFunction (value);
Resultlabel-> Caption = INTOSTR (RESULT)
/ / -------------------------------------------------------------------------------------------- ---------
Void __fastcall tform1 :: button3click (TOBJECT * Sender)
{
INT value = start (edit1-> text);
Int results = unknownfunction (Value);
Resultlabel-> Caption = INTOSTR (Result);
}
The issue brought by Visual C DLL is in the ideal world, the DLL that calls Visual C created will not be more difficult than the DLL built by C Builder. Unfortunately, Borland and Microsoft have a number of inconsistent places. First, Borland and Microsoft differ in the file format of the OBJ and the introduction library (Visual C uses the Coff library format, and Borland uses the OMF format). This means you can't add a Microsoft's introduction library to the C Builder engineering. Thanks to Borland Implib this utility, the file format is different. Two products are also different in connection names. This is the main obstacle to C Builder call Visual C DLL. Each function in the DLL or OBJ has a connection name. The connector connection name is resolved during the connection (resolve) declares the function of the prototype. If the connector does not find a function that it thinks is the connection name required by the program, it will generate unresolved external errors (Unresoled External Error). About the function connection name, Borland and Microsoft are different from the following two points:
1- Visual C Sometimes the __stddcall function exported. 2- Borland C Builder is considered a __cdecl function when introducing this modified function. So why is this important? Take different # 1 __stddcall call habits. If you create a DLL with Visual C , it contains a __stdcall modified function called MyFunction (), Visual C will give a function a connection name, to _myfunction @ 4. When the Borland connector is trying to resolve the constructor, it is considered to find a function called MyFunction. Because the Visual C DLL introduction library does not include a function called MyFunction, the Borland Connector reports an unresolved external error, and the awareness is not found. How to solve these three problems depends on the compilation method of Visual C DLL. I divide the whole process into four steps. Step 1: Identify the call habits used in Visual C DLL to fight with naming habits, you must first determine the call habits used in the DLL function. You can determine by viewing the header file of the DLL. The function prototype form in the DLL header is as follows: __Declspec (dllimport) void calling_convention myfunction (int NARG); calling_convent should be __stdcall or __cdecl (see Listing A). Many times, call habits are not specified, in this case, default, __cdecl. Step 2: Check the connection name in the DLL If you display the DLL use __stdcall call habits in step 1, you need to further check the DLL to determine the name habits used when you create it. Visual C By default, it is necessary to modify the __stdcall function, but if you write this DLL programmer adds a DEF file in their project, you can block naming modifications. If the supplier does not use the DEF file, your union will be slightly cumbersome. Command line tool TDUMP allows you to check the connection name of the DLL export function. The command of TDUMP is called to the DLL. TDUMP -EE -M mydll.dll> mydll.lst TDUMP can report a number of information about DLL. We are interested in DLL export functions. The -ee command option indicates that TDUMP lists only export information. -m switch tells TDUMP to display in the original format of the DLL function. If there is no -m switch, TDUMP will try to convert the modified function into people's easy-to-read format. If the DLL is large, you should redirect the output to a file (by additional> mydll.lst).
To test the output of the DLL TDUMP source program list A and B are as follows: Turbo Dump Version 5.0.16.4 Copyright (c) 1988, 1998 Borland International Display of File DLL.DLL EXPORT ord: 0000 = 'CdeclFunction' EXPORT ord: 0002 = 'UnknownFunction 'Export ORD: 0001 =' _ stdcallfunction @ 4 'Note Underline and suffix @ 4 on the __stdcall function. __cdecl and the function of the unidentified call mode do not have any modifiers. With the DEF file when VisualL C DLL is compiled, the modifier on the __stdcall function will not appear. Step 3: Generate an introduction library for Visual C DLL this is a key part. Due to the different library file formats of C Builder and Visual C , you cannot add an introduction library created by Visual C to your C Builder Engineering. You must create an introduction library of an OMF format with a command line tool issued with C Builder. Relying on the conclusions drawn above, this step or very smooth, or take some time. As mentioned earlier, C Builder and Visual C are inconsistent with how to give a DLL function. Due to the difference in naming habits, if C Builder and Visual C are not consistent with the DLL call habits, you need to create an introduction library with alias. Table A lists inconsistent places. Table A: Visual C and C Builder Name habits Call habits VC Name VC (using DEF) C Builder Name --------------------- ------------------------------------------
__stdcall _myfunction @ 4 myfunction myfunction
__cdecl myfunction myfunction _ myfunction C Builder column lists the connection name you want to find. The first Visual C column lists the connection name when the DEF file is not used in the Visual C project. The second Visual C column contains the connection name created by Visual C when using the DEF file. Note that the two products are only in one case: Visual C project contains the __stdcall function of the DEF file. Next, you need to create an introduction library with aliases, making Visual C named C Builder named. Table A shows several combinations that you may need to process when you create an introduction library. I divide the combination into two situations. The first case: DLL only contains the __stdcall function, and the DLL vendor uses the DEF file table a display, which is consistent with VC and C Builder when DLL uses the __stdcall function. Moreover, the DLL must be compiled with the DEF file to prevent the VC modified connection name. The header file will tell you whether to use __stdcall call habits (step 1), TDUMP will display the function to be modified (step 2). If the DLL contains the __stdcall function that is not modified, Visual C and C Buidler remain consistent on the function name. You can create an introduction library for DLL to DLL. No alias is required. The implib command format is as follows: Implib (DESTINATION LIB NAME), for example: Implib mydll.lib mydll.dll 2 case: DLL contains __cdecl function or modified __stdcall function If your DLL vendor insists Create a DLL that is independent of the compiler, you can fortunate it into the first situation. Unfortunately, there are several possibilities that you can't get it into the first situation. First, if the DLL supplier omitted the call habit when the function declares, the default is __cdecl, __ cdecl forced you to enter the situation 2. Second, even if your supplier uses the __stdcall call habits, they may ignore the modifiers that use the DEF file to remove Visual C . However, you found this, good day, welcome to the second situation. You are trapped with a DLL different from C Builder with a function name. The only way to get rid of this trouble is to create an introduction library, define a unique name that is compatible with the C Builder's format for Visual C . Fortunately, the C Builder command line tool allows you to create an introduction library with alias. The first step is to create a DEF file to the Visual C DLL with the IMPDEF program with the C Builder. The DEF file created by IMPDEF can list all functions exported by the DLL.
You can call iMPDEF: IMPDEF (Source DLL file), for example: IMPDEF mydll.def mydll.dll runs the impdef, select an editor to open the generated DEF file. The DEF files created by using Visual C compiles the source program list A and B generate the DLL. The DEF file created by IMPDEF is as follows: Exports; Use this type of aliansing
(Borland Name) = (Name Exported by Visual C )
_CDECLFunction = CDECLFunction
_Unknownfunction = unknownfunction
StdcallFunction = _STDCALLFunction @ 4 Next will modify the DEF file, so that the alias of the DLL function looks like the function of C Builder. You can create an alias for a DLL function, list a C Builder compatible name, and then pick up the original Visual C connection name. For procedures list A and B test DLL, the DEF with alias is as follows: Exports
Use this type of aliansing
(Borland Name) = (Name Exported by Visual C )
_CDECLFunction = CDECLFunction
_Unknownfunction = unknownfunction
StdcallFunction = _STDCALLFunction @ 4 Note that the function name on the left matches the name of the Borland compatible name in Table A. The function name on the right is the connection name of the real Visual C DLL function. The last step will create an alias from the alias DEF file into the library. You have to rely on the Implib utility, just this time, use the alias DEF file as a source file instead of its original DLL. The format is: IMPLIB (DEST LIB FILE), for example: Implib mydll.lib mydll.def creates an introduction library, but also proceed to the fourth step. You should first check the introduction library to ensure that each DLL function has a consistent naming format with C Builder. You can use the TLIB utility to check the library. Tlib mydll.lib, mydll.lst is the list file generated by the test DLL as follows: Publics by Module
Stdcallfunction size = 0
StdCallFunction
_CDECLFunction Size = 0
_CDECLFunction
_Unknownfunction size = 0
_Unknownfunction
Step 4: Adding the introduction library to your project Once you create an introduction library for Visual C DLL, you can add it to your C Builder project with menu project | add to project. You don't have to consider whether it contains an alias when you use the introduction library. After adding this introduction library to your project, build your project to see if it is a successful connection. Conclusion: This article demonstrates how to call the Visual C DLL in the C Builder engineering. These techniques take effect for the DLL created by C Builder 1 and C Builder 3, Visual C 4.x or Visual C 5 (I haven't tested Visual C 6). You may notice that this article only discusses how to call the DLL C style function. There is no way to call the Visual C DLL object. Because the connection name of the member function is adapted (Mangled), C DLL exhibits more difficult issues. The compiler uses a Name Mangling scheme to support function overload. Unfortunately, the C standard does not specify how the compiler should adapt to the method. Because there is no strict standard in place, Borland and Microsoft have developed their own technologies for the name, and the habits of both are not compatible. In theory, you can use the same alias technology to call a member function of a class in the DLL. But you should consider creating a COM object instead. COM brings a lot of its own problems, but it enforces the method of calling an object in a standard way. COM objects created by Visual C can be called in either development environment, including Delphi and C Builder. C Builder 3.0 introduces a new command line utility called Coff2omf.exe. This utility can convert the Visual C introduction library into C Builder's introduction library. In addition, the __cdecl function, this program will automatically generate aliases from Visual C formats to C Builder format. If the DLL dedicated __cdecl call habits, the automatic alias can simplify step 3.