Tech Support > Microsoft Windows > Development Resources > Where do Leading Underscores Come From?
Where do Leading Underscores Come From?
Posted by Larry Lindstrom on March 5th, 2004


Hi Experts:

I'm continuing my battle to get the Firebird
database engine working with my Windows project.
I have a post in the Firebird support group, but
this might be an issue with VC6.

We've all seen statements like "readit()" call
functions named "_readit". I've always assumed
the leading underscore was added by a macro
expansion. The process is usually transparent and
works and I've never spent any time thinking about
it.

Now I'm calling a function in the Firebird API
called isc_dsql_execute_immediate() and the build
generates the following error message:

error LNK2001: unresolved external symbol _isc_dsql_execute_immediate@28

Dumpbin tells me the Firebird DLL exports a
function called "isc_dsql_execute_immediate", but
does not have a function called
"_isc_dsql_execute_immediate", with a leading
underscore.

This is the function declaration in Firebird's
header after the preprocessor is finished with it.
Thank you Tim.

ISC_STATUS __stdcall isc_dsql_execute_immediate(...

If I understand correctly, __stdcall refers to
who, the caller or the called function, cleans up
the stack. Does this also cause a leading
underscore to be added to the function's name?

I don't see anything in Firebird's header file,
which I believe is the only influence Firebird has
on the compile, that would add the leading
underscore.

Where is this leading underscore coming from,
and what should I be doing to get this to compile?

Thanks
Larry


Posted by Tim Robinson on March 5th, 2004


Larry Lindstrom wrote:
[...]
It's part of normal C name decoration (normal on Windows at least).

Given a function called this,

ISC_STATUS isc_dsql_execute_immediate(...

....the compiler will add an reference in the object file to a symbol called
_isc_dsql_execute_immediate. This is cdecl name decoration.

Given a function called this,

ISC_STATUS __stdcall isc_dsql_execute_immediate(...

....the compiler will add a reference to a symbol called
_isc_dsql_execute_immediate@NN, where NN is the number of bytes in the
parameter list. This is stdcall name decoration.

What you need is an import library whose external functions use stdcall
naming, but which imports names without any decoration. Unfortunately I
don't know of a tool which will actually generate such an import library
(there used to be one in the compiler package).

By way of a hack, you could put together a .DEF file which gives the
functions whatever names you want, and imports them from the DLL by ordinal.
For instance, here's a few lines from a .DEF file I put together for a NTDLL
import library:

NAME ntdll.dll
CsrAllocateCaptureBuffer@8 @6 NONAME
CsrAllocateMessagePointer@12 @7 NONAME
CsrCaptureMessageBuffer@16 @8 NONAME
CsrCaptureMessageString@20 @9 NONAME
CsrCaptureTimeout@8 @10 NONAME
CsrClientCallServer@16 @11 NONAME

Then it's easy to use the LIB program to generate an import library from
this .DEF file.

However, this relies on the ordinals in the DLL being fixed, which will only
be the case if the authors of the DLL specified ordinals in /their/ .DEF
file, like this. Chances are they didn't.

The problem is that LIB seems to set the imported function name and the
external symbol name to the same string. That is, if you want to be able to
use a function in a DLL called Fred, you must declare it in your program
such that the compiler looks for a function called _Fred. This is a
limitation of the LIB tool, not of the compiler or linker, or the EXE file
format.

It would be trivial (though not necessarily easy) to write a program which
takes a DLL name and a map from export name (such as Fred) to symbol name
(such as _Fred@16), and generate an import library.

--
Tim Robinson (MVP, Windows SDK)
http://mobius.sourceforge.net/



Posted by Larry Lindstrom on March 5th, 2004


Tim Robinson wrote:
Thanks again Tim:

I didn't realize every function has an underscore
added to the name. I wonder what that accomplishes.

Firebird is based on an open source release of
Borland's Interbase. I'm wondering if they used
Borland's tools to build the binaries.

Do you know if a DLL built with Borland tools
is compatible with an app built with Visual C?

I'm finishing up my second week in an attempt to
get this going. A user of Borland's C++ compiler
who has tried to help me, in the comp.databases
newsgroup, told me he unzipped the package and
everything just worked.

Olof has guided me to a basic understanding
of converting dumpbin output to a .DEF file, and
then to an import library. But I need a deeper
explanation of the .DEF file's contents. Can
you point me to a resource on the web, or MSDN
online?

I'm thinking the next step is to attempt a
build of the binaries with MSC.

If that proves to be unfeasible I'll try to
build a .DEF.

If that doesn't work, I'll look for another
database. That will be a disappointment, Firebird
has four important features. It's free, people
who use it are enthuriastic about it, it handles
Unicode and it has an embedded server which allows
me to despense with the complexity of setting up a
separate server on the laptop application I'm
building.

Thanks
Larry

Posted by Tim Robinson on March 5th, 2004


Larry Lindstrom wrote:
Beats me. What you see -- in MSDN -- is what you get. Unless LIB.EXE has
some undocumented features, module definition (.DEF) files are documented
entirely within a couple of pages on MSDN.

Good luck. Given that it already builds with one Windows toolset (Borland),
it should build with Visual C++. But then who knows...

--
Tim Robinson (MVP, Windows SDK)
http://mobius.sourceforge.net/



Posted by Alex Blekhman on March 6th, 2004


Here's good explanation of calling conventions used in MSVC compiler.

"Calling Conventions"
<http://msdn.microsoft.com/library/en...re_Calling_Con
ventions_Topics.asp>

HTH
Alex



Similar Posts