views:

347

answers:

5

I have an x64 project in VS2008 that needs to include an old legacy library written in Fortran years ago. I do not have the source and cannot recompile it. The function names in the .lib are prepended with an underscore, but the x64 projects only use fastcall reference which does not want to recognize stdcall or cdecl references. Is there anything that will tell the build to recognize the names with prepended underscores?

EDIT

All moot points since once I got past the naming problem it ended up telling me fatal error LNK1112 : module machine type x86 conflicts with target machine type x64, so i can't link this old library in anyway.

+1  A: 

What language is your x64 project in? You should be able to specify the calling convention in your extern definition for the function:

  extern int __stdcall foo();
Rob Walker
+1  A: 

Names with prepended underscores are used by C linkage, so if your implementation language is C++ (is it?), you should use this declaration

extern "C" {
  int foo();
  float bar();
}

It should also use __cdecl, although I'm not sure about that.

jpalecek
+2  A: 

I'm assuming that your legacy library is 32 bit. Have you tried compiling your project as x86 instead of x64 to see if the problem is from the x64 compile? If that's the case, you could try the stuff here:

http://stackoverflow.com/questions/128445/calling-32bit-code-from-64bit-process

Ben Robbins
A: 

You mentioned Fortran from years ago, chances are very good it's 32-bit. The name-mangling (leading underscore) is the tip of the iceberge, even if you managed to fix this (calling convention issue), you'd still have the problem of calling 64-bit from 32-bit. The link by Ben Robbins above may help. We had a similar issue, we considered that perhaps we'd be able to wrap our 32-bit DLLs in COM wrappers and then call the COM wrappers from 64-bit. Don't know if that would work, as we ended up finding the source code and getting a good 64-bit compile.

Marc Bernier
A: 

You definitely need the header file. If you still have the problem, it means the definitions in the header don't specify the calling convention.

The general approach to handle linke errors:

  1. Dump the functions used by your application

    dumpbin /symbols

  2. Dump the library and and the dll

    dumpbin /exports dumpbin /exports

For static libraries

dumpbin /symbols <libraryFileName.lib>
  1. Find the function names in the 2 dumps (3 for the dll+import library) and make sure they are identical.

  2. Any mismatch you find will indicate what your problem is

  3. Change your call to end up with the same result as the exported stuff


Interpreting (some of) the results:

C functions:

_functionName = C function, __cdecl calling convention
_functionName@12 = C function, __stdcall calling convention
@functionName@12 = C function, __fastcall calling convention

(of course, the number does not have to be 12)

C++ functions

They look like ?functionName@ That is the decorated name. But the dump also contains the undecorated one.

Examples:

?functionName@@$$J0YMHHPADPAUKeyVal@@@Z
(extern "C" int __clrcall functionName(int,char *,struct KeyVal *))
=> you have all the info, including the fact that this is compiled to
managed code (__clrcall)

?functionName@@YAHHPADPAUKeyVal@@@Z
(int __cdecl functionName(int,char *,struct KeyVal *))
=> normal C++ function

?functionName@className@@QAEHHPADPAUKeyVal@@@Z
(public: int __thiscall className::functionName(int,char *,struct KeyVal
*))
=> member function (because of __thiscall) of the class className

And so on.


Tip: I recomand dump into a file because the resulting dumps can be big dumpbin /exports fileToDump.lib > dumpResult.txt

Bonus tip: sometimes in one dump you will see unsigned short and in another wchar_t This means the compilation was not done with the same settings for wchar_t (native type or not)

Mihai Nita