Solved

Calling a standard DLL from Visual C++

Posted on 2001-07-24
24
503 Views
Last Modified: 2013-12-14
I'm using MS Visual C++ 6.0

I have a DLL called "Adding". It's programmed in Borland Delphi (that really doesn't matter). I know the dll exports a function called "Add" which has the following header (in C++):

int __stdcall Add(int X, int Y);

Now I want to call the "Add" function from Visual C++. So I create a LIB-file by first creating a DEF file with the following content:

LIBRARY
  Adding
EXPORTS
  Add

and call lib from the commandline:
lib /DEF:Adding.def

And a LIB file is created. I also create a header file with the following content:

#ifdef __cplusplus
extern "C" {
#endif

int __stdcall Add(int X, int Y);

#ifdef __cplusplus
}
#endif

When I compile my project everything works fine, but the linker complains that it can't find a function called "_Add@8".

How do I make the LIB-file know that the decorated name "_Add@8" should link to the undecorated name "Add" in the DLL?

It must be possible, because if you inspect the DLL's that come with Windows then they contain no decorated names; but the LIB-files that ships with Visual C++ contains decorated names that links to the undecorated names in the DLL's!

Has Microsoft a secret trick, or am I missing something?

Thanks
Morten
0
Comment
Question by:mortenj
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
  • 5
  • +3
24 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 6312826
>>Has Microsoft a secret trick, or am I missing something?

I assume that it is a problem resulting of the MS/Delphi combination.

Try

dumpbin /exports adding.dll

to see with what naming convention the function is exported
0
 

Author Comment

by:mortenj
ID: 6312914
I have tried dumpbin /exports adding.dll it gave the following result:

Dump of file adding.dll

File Type: DLL

  Section contains the following exports for Adding.dll

           0 characteristics
           0 time date stamp Thu Jan 01 01:00:00 1970
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00003B4C Add

  Summary

        1000 .edata
        1000 .idata
        1000 .reloc
        1000 .rsrc
        1000 BSS
        3000 CODE
        1000 DATA

As far as I can see it only exports "Add" (it looks very much like the result you get by using dumpbin on a DLL that comes with Windows).
0
 
LVL 22

Expert Comment

by:nietod
ID: 6312930
To continue that thought, if the dll exports a function called "add" not "_add@8" this suggests that the function is not using the standard call calling convention, and might be using the C-decl calling conbnetion.  so you will need to make sure that you call the function with the right calling conbention.  (Although I would have thought that delphi does use standard call by default, but I'm not sure.)

>> How do I make the LIB-file know that the decorated name "_Add@8"
>> should link to the undecorated name "Add" in the DLL?
Changing to the cdecl calling convetion will remove the standard call decoration you see.  Howver it is possible that you still want the standard call calling conbention, just not the deocration  
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:nietod
ID: 6312945
In that case try

nt __cdecl Add(int X, int Y);

That should link.  But it might crash when you call it.  Just try it and see.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6312974
>>When I compile my project everything works fine, but the
>>linker complains that it can't find a function
>>called "_Add@8".

Hmm, the underscore sort of says that the compiler uses the 'C' naming convention - see a related MSJ article at http://www.microsoft.com/msj/defaulttop.asp?page=/msj/archive/s330.htm

Try to alter your .der file:

LIBRARY
 Adding
EXPORTS
 _Add=Add
0
 

Author Comment

by:mortenj
ID: 6316571
1) The dll is using stdcall calling convention. It's produced by Delphi, and Delphi doesn't add any name decoration to stdcall functions (it produces DLL's that looks like the Win32 API DLL's)

2) If I did use cdecl calling convention, then everything works fine using the sceme I described - I get no linker errors. But to make the DLL look as much as possible as a Win32 API DLL I prefer the stdcall calling convention!

I guess I can formulate my question another way:
"Suppose you have a Win32 API DLL and a piece of paper describing the exported functions. Lets say you've lost the according LIB-file that comes with Visual C++. Is there a way you can use that DLL from Visual C++? (i.e. you have to create the LIB-file yourself)"

The article jkr gave a link to, sort of indicates that you can't - this means that if you want to create a DLL that people can use from any programming language (like a Win32 API dll) you get stuck using Visual C++...

But again how does Microsoft do it? Are the Win32 API DLL's created using Visual C++ (in which case the LIB-files are generated automatically)?

Btw. My current solution is to export two functions from the Delphi DLL: one named "Add" and one named "Add@8" and they both point to the same internal function in the DLL. My DEF-file then looks like:
LIBRARY Adding
EXPORTS
  Add
  Add@8
Note that "lib /DEF:Adding.def" automatically adds the underscore in front of the names.
It works but it's not elegant!!

Thanks for all your comments/answers - I'm still hoping for a nifty workaround!

Morten
0
 
LVL 22

Expert Comment

by:nietod
ID: 6316815
>>  If I did use cdecl calling convention, then everything works fine
>> using the sceme I described - I get no linker errors.
But if you are right that the function uses stdcall as the calling convention then everything shoudl liknf fine, but should not run fine.  It should crash when you call the function.   Does it?  if it does not then the function is not stdcall.

>> Is there a way you can use that DLL from Visual C++?
>> (i.e. you have to create the LIB-file yourself)"
You can create an import library from a DLL.  but you alredy have the import library, right?  Otherwise you couldn't have gotten this to link.

0
 

Author Comment

by:mortenj
ID: 6316995
>>But if you are right that the function uses stdcall as
>>the calling convention then everything shoudl
>>liknf fine, but should not run fine.  It should crash
>>when you call the function.   Does it?  if it
>>does not then the function is not stdcall.

That's excatly the point!! It doesn't link!! When you compile a DLL with Delphi using stdcall then the DLL exports the exact name (i.e. "Add") and you will get no LIB-file you can use with Visual C++ (I create the DLL in Delphi myself, so I _know_ that it uses stdcall).

When you compile a DLL with Visual C++ using stdcall it exports "_Add@8" (try it yourself). But you can make the DLL export only "Add" by using a DEF file - but when you create a DLL in Visual C++ you automatically create a LIB-file, and this LIB-file will in any case contain "_Add@8" so you can allways call the DLL from Visual C++ programs without any problems.

I only have the Delphi DLL and no LIB file!!! And if I create a LIB-file using the lib-commandline-tool then this LIB-file will only contain reference to "_Add" (underscore added automatically), but the Visual C++ linker requires that the LIB-file contains reference to "_Add@8".

>>You can create an import library from a DLL.  but you
>>alredy have the import library, right?  Otherwise
>>you couldn't have gotten this to link.
I can't link it!! What I'm asking is:

If I give you a DLL which exports a function called "Add" and I tell you that the function has the following header:

int __stdcall Add(int X, int Y);

Can you with only these two informations (no LIB-file or anything else), create a Visual C++ program that use this DLL?

I know I can create a program in Delphi, Borland C++ and others without any problems - but I can't in Visual C++!!

Morten



0
 
LVL 86

Expert Comment

by:jkr
ID: 6317039
Did you try modifying the .def file?

LIBRARY
Adding
EXPORTS
_Add=Add

should give you the name mapping and allow you to stay with '__stdcall'...
0
 

Author Comment

by:mortenj
ID: 6317070
>>Did you try modifying the .def file?
>>LIBRARY
>>Adding
>>EXPORTS
>>_Add=Add
>>should give you the name mapping and allow you to stay
>>with '__stdcall'...

Yes I tried that, but the leading underscore is not the problem, it's the @8 in the end. If you think about it, it seems reasonable that lib cannot create a lib-file containing a reference to "_Add@8" when it from the DEF-file doesn't the number and type of parameters that Add takes...
0
 
LVL 22

Expert Comment

by:nietod
ID: 6317100
>>  you will get no LIB-file you can use with Visual C++
Its not the lib file that is the problem.  its the DLL.  The lib file will just reflec the exported name that appears in the DLL's exports lits.   You coudl create a doctored LIB file that had the decorated name, but then when you ran your program it would fail to dynamci link with the DLL and windows would termiante it.

The "problem" is not in the lib, its in the DLL

>> Icreate the DLL in Delphi myself, so I _know_ that it uses stdcall).
A simple fix would be to use cdecl in the DLL then.

>> Can you with only these two informations (no LIB-file or anything
>> else), create a Visual C++ program that use this DLL?
You can always use explicit linking to make the link.  I.e. load the DLL with LoadLibrary() and then find the function using its undecorated name in GetProcAddress().

but jkr believes that you can use an alias in your program's module definition file (.DEF) to make this link implicitly.  i don't know if that is right or not, but knowing jkr I would certainly try it before giving up!!! Did you try it?
0
 
LVL 86

Expert Comment

by:jkr
ID: 6317119
LIBRARY
Adding
EXPORTS
_Add@8=Add
0
 

Expert Comment

by:westaf
ID: 6317180
The "_Add@8" you got is the Microsoft C++ mangling of your function symbol. Every C++ compiler mangles C++ symbols because C++ functions may have overloads which have the same name but with different parameters.
Well, you just delete the #ifdef - #endif pair and your code will get compiled. Just like this:

extern "C" {

int __stdcall Add(int X, int Y);

}

This references exactly the "Add" symbol, and is exactly an stdcall function with 2 32-bit int parameters.
0
 

Author Comment

by:mortenj
ID: 6317258
>>LIBRARY
>>Adding
>>EXPORTS
>>_Add@8=Add

First: the leading underscore is added automatically by lib-commandline-tool, so to make it link you have specify:
LIBRARY
Adding
EXPORTS
  Add@8=Add

And yes this will make the program link!! But an error will arise when you run the diagram: "The procedure entry point Add@8 could not be located in the dynamic link library Adding.dll"

You can actually test this problem using only Visual C++. If you create the Adding.dll in Visual C++ using the following code:

int __stdcall Add(int A,int B)
{
  return A+B;
};

and include the following DEF-file:

LIBRARY  Adding
EXPORTS
  Add

Delete the LIB-file created when you compiled the DLL, and thereafter try to use the DLL in a Visual C++ program.
0
 

Author Comment

by:mortenj
ID: 6317286
To westaf:

No not excatly, Visual C++ also adds what is known as "__stdcall name mangling" this means that

extern "C" {
  int __stdcall Add(int X, int Y);
}

is interpreted by the Visual C++ linker as "_Add@8" - even thoug you use extern "C"!!!


0
 
LVL 22

Expert Comment

by:nietod
ID: 6317423
>> Every C++ compiler mangles
>> C++ symbols because C++ functions may have overloads
No, this is not the C++ decoration.  The extern "C" removes that.   This is the windows standard call decaration which is unrelated.  It expreses the size of the parameters in bytes.  This is an attempt to insure that the caller and called function agree on the parmaeter size since that is extremely important when using standard call.  its less of a problem--slightly--in c-decl.

Is there a reason why you have to use standard-call?

How impractical would it be to use explicit linking?
0
 
LVL 86

Expert Comment

by:jkr
ID: 6317435
>>Is there a reason why you have to use standard-call?

It's a Delphi DLL, if I'm not mistaken...

0
 
LVL 22

Expert Comment

by:nietod
ID: 6317466
I would think delphi would still have c-decl as an option.  wsprintf() is c-decl for instance, there might be others.  it can't use those OS features without the ability to make c-decl calls.
0
 

Author Comment

by:mortenj
ID: 6317526
Yes I could use cdecl calling convention (and everything would work fine) - but I just thought that if you create a DLL which people can use with their preferred compiler/language, then you should stick to the stdcall calling convention, because this is the calling convention used in the Windows API (so all compilers should be able to link to the DLL). It then turns out that you the only problem is Visual C++, which can't use stdcall DLL's except if they are created in Visual C++... Bummer...

To nietod: Yes I could use explicit linking, but it's very impractical...

I think I'll stick with the solution of making Delphi export both "Add" and "Add@8" - i.e. to use Visual C++ you need a twice as big export table in your DLL...
0
 

Accepted Solution

by:
Wolfie320 earned 300 total points
ID: 6787791
Hi morteni!

I just had the same kind of problem that you have (had)!

Did create a dll using VC++ no problem, looks fine and I can us it from Delphi.
Then when I tryed to use it from VC++ I did get the same error when linking.

The problem is your .lib file as you say.
Check this out...

dumpbin /exports from my .dll

          2    0 0000101E CreateGLWindow
          1    1 00001028 Init

dumpbin /exports from my .lib

          2    _CreateGLWindow@16
          1    _Init@0

The dll project did create my lib file using a .def file and function prototype declarations. Think that is what you are missing. Function prototypes...

Try this...

Add a .def file like my.. to a VC++ project

LIBRARY IFSOpenGL
DESCRIPTION "OpenGL window control test by Wolf"
EXPORTS
     Init          @1
     CreateGLWindow     @2

then a header file describing the functions...

extern "C" int __stdcall Init();
extern "C" HWND __stdcall CreateGLWindow(HWND parentWnd, int width, int height, int bits);

Hope this will help you. If you want a code example just ask...

regards

/Wolfie320  


0
 
LVL 22

Expert Comment

by:nietod
ID: 6787901
Wolfie320, this question is nearly a year old!
0
 

Expert Comment

by:Wolfie320
ID: 6790644
I know... but if someone have this kind of problem, like I did. They may wan't to have some sort of answer.
This is a common problem when using VC++ and extern "C" __stdcall
0
 
LVL 22

Expert Comment

by:nietod
ID: 6790979
In that case post it is a comment not an answer.  The question has been abandoned.
0
 
LVL 11

Expert Comment

by:griessh
ID: 7021835
Dear morteni

I think you forgot this question. I will ask Community Support to close it unless you finalize it within 7 days. You can always request to keep this question open. But remember, experts can only help you if you provide feedback to their questions.
Unless there is objection or further activity,  I will suggest to accept

     "wolfie320"

comment(s) as an answer.

If you think your question was not answered at all, you can post a request in Community support (please include this link) to refund your points. The link to the Community Support area is: http://www.experts-exchange.com/commspt/

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
======
Werner
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Programmer's Notepad is, one of the best free text editing tools available, simply because the developers appear to have second-guessed every weird problem or issue a programmer is likely to run into. One of these problems is selecting and deleti…
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

718 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question