原文链接: http://www.coopknow.com/papers.asp?paper=2
Many people incorrectly think the C and C++ languages are the same. Although C++ evolved from C and C++ compilers can compile C, the functionality of the two languages is different. C++ is a complete object-oriented language. It supports inheritance, information hiding, polymorphism and operator overloading. C does not have these features.
C++ was originally implemented as a pre-processor to a standard C compiler. The pre-processor parsed the C++ source code and generated C source. A C compiler then compiled the generated source code. There was, however, a problem generating the C source. C++ supports polymorphism (having two or more functions with the same name) but C does not allow two functions to have the same name. They solved this by invoking a pre-processor. It generated a C function name by combining the specified C++ function name and the return and argument types of the function. This solution was called "name mangling." Although modern C++ compilers do not use the pre-processor to generate C source anymore, they still mangle function names. This technique works great so long as all functions involved are C++ functions.
Microsoft Windows DLL external functions do not conform to the C++ naming convention. Their names cannot be mangled by C++ and they do not use the C argument standard. They must be of type PASCAL. In addition, Windows does not support the C++ object/class structure. It just does not know what to do with a pointer to an instantiated object. This does not mean that you cannot use C++ in a DLL, you just need to use a special technique called "wrapping."
C++ Wrappers
This is not a new problem in the C/C++ world. When programmers started using C++ to enhance systems written in C, they needed some way to allow C functions (functions that had no knowledge of C++ calling conventions) to call the methods of C++ objects. They wrote wrapper functions to do this. A wrapper functions is a C function that is compiled as if it were a C++ function. Because the wrapper is compiled as a C++ function, it understands the C++ calling conventions. Since it is a C function, other C functions can call it. Anytime a non-wrapper C function needs to call a C++ class method, it calls the wrapper function and requests the wrapper to make the call for it.
Sample Wrapper Functions
In a Windows DLL, the wrapper functions are the exported functions of the DLL. Let me show a small example of this.
C++ class description in file cls.cpp
class clsC wrapper functions in file clswrap.cpp:
{public:};
cls();
~cls();
int doit(int x);
extern "C"
{void * PASCAL _extern CLSConstruct();};
void PASCAL _extern CLSDestruct(void *Cls);
int PASCAL _extern CLSDoit(void *Cls,int x);
void * PASCAL _extern CLSConstruct()
{cls *obj;}
obj = new cls;
return(void *)obj))
void PASCAL _extern CLSDestruct(void *Cls)
{
cls *obj;}
obj = (cls *)cls;
delete obj;
int PASCAL _extern CLSDoit(void *Cls,int x)C function calling the wrapper in file use.C
{cls *obj;}
obj = (cls *)Cls;
return(obj->doit(x));
use()
{void *cls;}
int x;
cls = CLSConstruct();
x = CLSDoit(cls,1);
CLSDestruct(cls);
In VB you can use the following:
Declare Function CLSConstruct Lib "cls.dll" As Long
Declare Sub CLSDestruct Lib "cls.lib" (ByVal cls as Long)
Declare Function CLSDoit Lib "cls.lib" (ByVal x as Integer) As Integer
Dim cls as Long
Dim r As Integer
cls = CLSConstruct
r = CLSDoit(cls,2)
CLSDestruct cls
Implementation Notes:
- The constructor wrapper function must return a pointer to the object that it instantiated. I use this pointer in all subsequent calls to the wrapper functions. I normally have it as the first argument of all other class method wrapper functions.
- I name the wrapper functions with the class name as the first part of the name and the method name as the second part.
- If the class method can take different arguments, then I write individual wrapper functions with unique names for each method.
Conclusion
If you want to write Windows DLL's in C++ you certainly can. You just need to write wrapper functions to export the function names to other Windows applications. I recommend that you only use C++ if you plan to use object-oriented programming techniques. If all you need is a simple function that you can easily write in C, why add the complexity of C++ and wrappers?