[轉貼]使用 Visual C++ DLLs in a C++Builder Project |
|
axsoft
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:681 回覆:1056 積分:969 註冊:2002-03-13 發送簡訊給我 |
Using Visual C++ DLLs in a C++Builder Projec
===============================================
來源 :http://www.bcbdev.com/articles/vcdll.htm
作者 :Harold Howe.
e-mail:hhowe@bcbdev.com It is likely that one day your boss will ask you if you can create a GUI with C++Builder that interfaces to an existing 32 bit DLL compiled with Microsoft Visual C++. Often times, the original DLL source code won't be available to you, either because the DLL comes from a third party vendor, or because the 22 year old intern just deleted the \DLL\SRC directory from the network. Given a DLL and a header file, this article shows you how to call the DLL from your C++Builder project. Calling DLL functions from a C++Builder project
The problem with Visual C++ DLLs
Step 1: Identify calling conventions used by the Visual C++ DLL
Step 2: Examine the linker names in the DLL
Step 3: Generate an import library for the Visual C++ DLL
Step 4: Add the import library to your project
Conclusion Calling DLL functions from a C++Builder project
Calling a DLL that was created with Visual C++ presents C++Builder programmers with some unique challenges. Before we attempt to tackle DLLs generated by Visual C++, it may be beneficial to review how you call a DLL that was created with C++Builder. A DLL that was created with C++Builder presents fewer roadblocks than one that was made by Visual C++. 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. 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. //------------------------------------------
// 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;
} 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. 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. 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. //------------------------------------------
// Listing C: MAINFORM.CPP - DLLTest program
#include
|
axsoft
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:681 回覆:1056 積分:969 註冊:2002-03-13 發送簡訊給我 |
Using Visual C DLLs in a C Builder ProjectPart 2: C classes. 資料來源:http://www.bcbdev.com/articles/vcdll2.htm Note: This article describes how to import C class from a Visual C DLL into an BCB project. Before we get started, I feel compelled to provide a small warning. This article is not really ready for mass distribution. I apologize if the 'article' seems choppy, difficult to read, or contains mistakes. I haven't have much time to polish it up. The only reason I decided to go ahead and publish this is because lots of developers ask how to do this. I figure that a poorly written article is better than nothing at all. I hope that this incoherent collection of ideas will prove helpful to you. In a previous article on how to use VC DLLs from MSVC, I describe how to create a Borland compatible import library for an MSVC DLL. The main difficulty in using the VC DLL is that MSVC and Borland use different formats for function names. For example, Borland expects __cdecl functions to have a leading underscore in front of them, whereas MSVC does not. Fortunately, you can surmount these naming problems using some of Borland's command line utilites, namely TDUMP, IMPLIB, IMPDEF and COFF2OMF. The idea is that you use the command line tools to create a Borland compatible import library with Borland compatible function names in it. Once you have a Borland compatible import library, you're set. You can simply link with the import library to use the MSVC DLL. Unfortunately, this strategy doesn't completely get you out of the woods. At the end of the DLL article, I drop a small bombshell. You can only call functions in the MSVC DLL if they are plain C functions. You can't import classes or class member functions. Doh! So what do you do if you need to import C class from an MSVC DLL? Uh...well, in that case, you are boxed into a corner, and your choices are limited (and usually when your backed into a corner, your options are not that pleasant). This articles describes three ways to get yourself out of that corner. Bad news: Before you waste too much time reading this diatribe, I feel, once again, compelled to issue a warning. All three of my techniques require that you have Microsoft Visual C . You don't need to have the source code for the DLL that you need to call, but you do need to have the tool that can call it. Each of the three techniques are more or less wrapping techniques where we use MSVC to wrap the DLL in something we can use from BCB. * Summary of the three techniques * Technique 1: Flattening the C class into a C library * Technique 2: Create a COM wrapper * Technique 3: Use an abstract base class with virtual functions (pseudo-COM) * Conclusion * Downloads Summary of the three techniques Ok, let the ugliness begin. Here are the three techniques. 1. Create a DLL with MSVC that flattens the C classes into plain C functions. The plain C functions will be imported from BCB. 2. Create a COM object with MSVC that wraps the C classes via containment. BCB will be a COM client of the VC COM object. 3. Wrap the C classes using an abstract class with nothing but virtual functions in it. This is essentially COM without the ugly parts. Each technique is described in more detail below. In each example, we will assume that the MSVC DLL exports a class that looks like this: class CFoo { public: CFoo(int x); ~CFoo(); int DoSomething(int y); }; Technique 1: Flattening the C class into a C library From the previous article on VC DLLs, we know that it is possible for a Borland project to call plain C functions that are exported from an MSVC DLL. Using this information, we can create a DLL project in MSVC that exports plain C functions for use in BCB. This MSVC wrapper DLL will be a client of the C DLL. The wrapper DLL will export plain C functions for creating CFoo objects, for calling CFoo member functions, and for deleting the CFoo object. The CFoo class contains three functions that we care about: the constructor, the destructor, and the all important DoSomething function. We need to flatten each of these into an equivalent C function. // original class class CFoo { public: CFoo(int x); ~CFoo(); int DoSomething(int y); }; // flattened C code void* __stdcall new_CFoo(int x) { return new CFoo(x); } int __stdcall CFoo_DoSomething(void* handle, int y) { CFoo *foo = reinterpret_cast |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |