⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vcdll.htm

📁 C++builder学习资料C++builder
💻 HTM
📖 第 1 页 / 共 2 页
字号:
decorates <TT>__stdcall</TT> functions by default, but the DLL programmer can prohibit name

decorations if they add a DEF file to their project. Your work will be slightly more tedious if the DLL supplier did not

use a DEF file.

</P>

<P>

The command line <TT>TDUMP</TT> utility allows you to examine the linker names of functions exported by the DLL. The following

command invokes <TT>TDUMP</TT> on a DLL.

</P>

<PRE>

    TDUMP -ee MYDLL.DLL &gt; MYDLL.LST

</PRE>

<P>

<TT>TDUMP</TT> can report a ton of information about the DLL. We're only interested in functions exported by the DLL. The

<TT>-ee</TT> command option instructs <TT>TDUMP</TT> to list only export information.

If the DLL is large, you may want to redirect the output of <TT>TDUMP</TT> to a file (via the <TT>&gt; MYDLL.LST</TT> appendage).

</P>

<P>

The <TT>TDUMP</TT> output for the test DLL in Listing A and B looks like this:

</P>

<PRE>

    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'

</PRE>

<P>

Notice the leading underscore and the trailing <TT>@4</TT> on the <TT>__stdcall</TT> function. The <TT>__cdecl</TT> and

the unknown function don't contain any decorations. If the Visual C++ DLL had been compiled with a DEF file, the

decorations on the <TT>__stdcall</TT> function would not be present.

</P>

<BR>

<H3>

<A NAME="step3">Step 3: Generate an import library for the Visual C++ DLL</A>

</H3>

<P>

Here comes the hard part. Due to the library file format differences between C++Builder and Visual C++, you cannot

add an import library created with Visual C++ to your C++Builder project. You must create an OMF import library using

the command line tools that come with C++Builder. Depending out what you found in the first two steps, this step will

either go smoothly, or it could take some time.

</P>

<P>

As stated earlier, C++Builder and Visual C++ don't agree on how functions should be named in a DLL. Due to naming

convention differences, you will need to create an aliased import library if the DLL implements calling conventions

where C++Builder and Visual C++ disagree. Table A lists the areas of disagreement.

</P>

<PRE>

<B>Table A: Visual C++ and C++Builder naming conventions</B>



Calling convention  VC++ name       VC++ (DEF used)     C++Builder Name

-----------------------------------------------------------------------

__stdcall           _MyFunction@4   MyFunction          MyFunction

__cdecl             MyFunction      MyFunction          _MyFunction

</PRE>

<BR>

<P>

The C++Builder column lists function names that the Borland linker expects to see. The first Visual C++ column

lists the linker names that Visual C++ generates when the Visual C++ project does not utilize a DEF file. The

second Visual C++ column contains linker names that Visual C++ creates when a DEF file is used. For things to go

smoothly, the C++Builder name should agree with the Visual C++ name. Notice that the two products agree in only one

place: <TT>__stdcall</TT> functions where the Visual C++ project contained a DEF file. For the remaining scenarios,

you will need to create an import library that aliases the Visual C++ name to a C++Builder compatible name.

</P>

<P>

Table A shows that there are several combinations that you may need to deal with when creating the import

library. I have separated the combinations into two cases.

</P>

<H4>Case 1: The DLL contains only <TT>__stdcall</TT> functions and the DLL vendor utilized a DEF file.</H4>

<P>

Table A reveals that VC++ and C++Builder agree only when the DLL uses <TT>__stdcall</TT> functions. Furthermore, the DLL

must be compiled with a DEF file to prevent VC++ from decorating the linker names. The header file will tell you if the

<TT>__stdcall</TT> calling convention was used (Step 1), and <TT>TDUMP</TT> will reveal whether or not the functions

are decorated (Step 2). If the DLL contains <TT>__stdcall</TT> functions that are not decorated, then Visual C++ and

C++Builder agree on how the functions should be named. You can create an import library by running <TT>IMPLIB</TT> on

the DLL. No aliases are needed.

</P>

<P><TT>IMPLIB</TT> works like this:

</P>

<PRE>

    IMPLIB (destination lib name) (source dll)

</PRE>

<P> For example,</P>

<PRE>

    IMPLIB mydll.lib mydll.dll

</PRE>



Create the import library and move on to step 4.



<H4>Case 2: The DLL contains <TT>__cdecl</TT> functions or decorated <TT>__stdcall</TT> functions.</H4>

<P>

If your DLL vendor is adamant about creating DLLs that are compiler independent, then you have a good chance of falling

into the Case 1 category. Unfortunately, odds are you won't fall into the Case 1 group for several reasons. For one, the

calling convention defaults to <TT>__cdecl</TT> if the DLL vendor omits a calling convention when prototyping the functions,

and <TT>__cdecl</TT> forces you into Case 2. Secondly, even if your vendor has utilized the <TT>__stdcall</TT> calling

convention, they probably neglected to utilize a DEF file to strip the Visual C++ decorartions.

</P>

<P>

However you got here, Good Day, and welcome to Case 2. You're stuck with a DLL whose function names don't agree with

C++Builder. Your only way out of this mess is to create an import library that aliases the Visual C++ function names

into a format compatible with C++Builder. Fortunately, the C++Builder command line tools allow you to create an aliased

import library.

</P>

<P>

The first step is to create a DEF file from the Visual C++ DLL by using the <TT>IMPDEF</TT> program that comes with

C++Builder. <TT>IMPDEF</TT> creates a DEF file that lists all of the functions exported by the DLL.

You invoke <TT>IMPDEF</TT> like this:

</P>

<PRE>

    IMPDEF (Destination DEF file) (source DLL file).

</PRE>

<P>For example</P>

<PRE>

    IMPDEF mydll.def mydll.dll

</PRE>

<P>

After running <TT>IMPDEF</TT>, open the resulting DEF file using the editor of your choice. When the DLL source in

Listing A and B is compiled with Visual C++, the DEF file created by <TT>IMPDEF</TT> looks like this:

<P>

<PRE>

    LIBRARY     DLL.DLL



    EXPORTS

        CdeclFunction        @1

        UnknownFunction      @3

        _StdCallFunction@4   =_StdCallFunction      @2

</PRE>

<P>

The next step is to alter the DEF file so it aliases the DLL functions into names that C++Builder will like. You

can alias a function by listing a C++Builder compatible name followed by the original Visual C++ linker name.  For the

test DLL in Listing A and B, the aliased DEF looks like this:

</P>

<PRE>

    EXPORTS

      ; use this type of aliasing

      ; (Borland name)   = (Name exported by Visual C++)

        _CdeclFunction   = CdeclFunction

        _UnknownFunction = UnknownFunction

        StdCallFunction  = _StdCallFunction@4

</PRE>

<P>

Notice that the function names on the left match the Borland compatible names from Table A. The function names on the

right are the actual linker names of the functions in the Visual C++ DLL.

</P>

<P>

The final step is to create an aliased import library from the aliased DEF file. Once again, you rely on the <TT>IMPLIB</TT>

utility, except that this time, you pass <TT>IMPLIB</TT> the aliased DEF file as its source file instead of the original

DLL. The format is

</P>

<PRE>

    IMPLIB (dest lib file) (source def file)

</PRE>

<P>For example</P>

<PRE>

    IMPLIB mydll.lib mydll.def

</PRE>

<P>

Create the import library and move on to step 4. You may want to examine the import library first to ensure that

each DLL function appears in a naming format that C++Builder agrees with. You can use the <TT>TLIB</TT> utility to

inspect the import library.

</P>

<PRE>

    TLIB mydll.lib, mydll.lst

</PRE>

<P>

The list file for the test DLL looks like this:

</P>

<PRE>

    Publics by module



    StdCallFunction size = 0

            StdCallFunction



    _CdeclFunction  size = 0

            _CdeclFunction



    _UnknownFunction size = 0

            _UnknownFunction

</PRE>

<BR>

<H3>

<A NAME="step4">Step 4: Add the import library to your project</A>

</H3>

<P>

Once you create an import library for the Visual C++ DLL, you can add the import library to your C++Builder project

using the <I>Project | Add to Project</I> menu option. You use the import library without regard to whether the import

library contains aliases or not. After adding the import library to your project, build your project and see if you can

successfully link.

</P>



<BR>

<H3>

<A NAME="conclusion">Conclusion:</A>

</H3>

<P>

This article demonstrated how you can call functions in a Visual C++ DLL from a C++Builder project.

The techniques work with C++Builder 1 and C++Builder 3, and DLLs built with Visual C++ 4.X or Visual C++ 5

(I haven't tested Visual C++ 6 yet).

</P>

<P>

You may have noticed that this article only discusses how to call C style functions in a DLL. No attempt is made to

call methods of an object where the code for the class resides in a Visual C++ DLL. C++ DLLs present an even greater

array of problems because linker names for member functions are mangled. The compiler employs a name mangling scheme

in order to support function overloading. Unfortunately, the C++ standard does not specify how a compiler should mangle

class methods. Without a strict standard in place, Borland and Microsoft have each developed their own techniques for

name mangling, and the two conventions are not compatible. In theory, you could use the same aliasing technique to call

member functions of a class that resides in a DLL. However, you may want to consider creating a COM object instead.

COM introduces many of its own problems, but it does enforce a standard way of calling methods of an object.

A COM object created by Visual C++ can be called from any development environment, including both Delphi and C++Builder.

</P>

<P>

C++Builder 3.0 introduced a new command line utility called <TT>COFFtoOMF.EXE</TT>. This utility can convert a Visual

C++ import library to a C++Builder import library. Furthermore, the program will automatically alias <TT>__cdecl</TT>

functions from the Visual C++ format to the C++Builder format. The automatic aliasing can simplify Step 3 if the DLL

exclusively uses the <TT>__cdecl</TT> calling convention.

</P>





</TD> </TR>



</TABLE>

</CENTER>

</BODY>

</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -