tags:

views:

3618

answers:

7

I'm writing a C/C++ DLL and want to export certain functions which I've done before using a .def file like this

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

with the code defined as this, for example:

int Foo(int a);
void Bar(int foo);

However, what if I want to declare an overloaded method of Foo() like:

int Foo(int a, int b);

As the def file only has the function name and not the full prototype I can't see how it would handle the overloaded functions. Do you just use the one entry and then specify which overloaded version you want when passing in the properly prototyped function pointer to LoadLibrary() ?

Edit: To be clear, this is on Windows using Visual Studio 2005

Edit: Marked the non-def (__declspec) method as the answer...I know this doesn't actually solve the problem using def files as I wanted, but it seems that there is likely no (official) solution using def files. Will leave the question open, however, in case someone knows something we don't have overloaded functions and def files.

+5  A: 

In the code itself, mark the functions you want to export using __declspec(dllexport). For example:

#define DllExport __declspec(dllexport)

int DllExport  Foo( int a ) {
  // implementation
}
int DllExport Foo( int a, int b ) {
  // implementation
}

If you do this, you do not need to list the functions in the .def file.

Alternatively, you may be able to use a default parameter value, like:

int Foo( int a, int b = -1 )

This assumes that there exists a value for b that you can use to indicate that it is unused. If -1 is a legal value for b, or if there isn't or shouldn't be a default, this won't work.

Edit (Adam Haile): Corrected to use __declspec as __dllspec was not correct so I could mark this as the official answer...it was close enough.

Edit (Graeme): Oops - thanks for correcting my typo!

Graeme Perrow
A: 

In the code itself, mark the functions you want to export using __declspec(dllexport). For example:

So, no way of doing this with a def file? I'm adding an overload to some legacy code that uses a def and was trying to avoid having to change a lot just to do that one function.

Adam Haile
+6  A: 

Function overloading is a C++ feature that relies on name mangling (the cryptic function names in the linker error messages).

By writing the mangled names into the def file, I can get my test project to link and run:

LIBRARY "TestDLL"
EXPORTS
    ?Foo@@YAXH@Z
    ?Foo@@YAXHH@Z

seems to work for

void Foo( int x );
void Foo( int x, int y );

So copy the C++ function names from the error message and write them into your def file. However, the real question is: Why do you want to use a def file and not go with __declspec(dllexport) ?

The mangled names are non-portable, I tested with VC++ 2008.

Timbo
A: 

@Timbo Yes, I know, def files are the "old" way of doing it...but as I said, this was some legacy code I was working with and there was nothing to warrant the time required to go through the whole thing and add __declspec(dllexport) to every exported function and remove the def file. Normally I don't use def files....which is why I was asking the question.

Edit: And regarding your "mangled names" method...nice one, that definitely does work, and those are the exact names dumpbin outputs for the exports... however I was looking for if there was an official way to do this that wasn't a hack and would be portable.

Adam Haile
+1  A: 

There isn't a language or version agnostic way of exporting an overloaded function since the mangling convention can change with each release of the compiler.

This is one reason why most WinXX functions have funny names like *Ex or *2.

MSN

Mat Noguchi
+2  A: 

There is no official way of doing what you want, because the dll interface is a C api.

The compiler itself uses mangled names as a workaround, so you should use name mangling when you don't want to change too much in your code.

Christopher
+1  A: 

I had a similar issue so I wanted to post on this as well.

  1. Usually using

    extern "C" __declspec(dllexport) void Foo();
    

    to export a function name is fine. It will usually export the name unmangled without the need for a .def file. There are, however, some exceptions like __stdcall functions and overloaded function names.

  2. If you declare a function to use the __stdcall convention (as is done for many API functions) then

    extern "C" __declspec(dllexport) void __stdcall Foo();
    

    will export a mangled name like _Foo@4. In this case you may need to explicitly map the exported name to an internal mangled name.

A. How to export an unmangled name. In a .def file add

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

This will try to find a "best match" for an internal function Foo and export it. In the case above where there is only one foo this will create the mapping

Foo = _Foo@4

as can be see via dumpbin /EXPORTS

If you have overloaded a function name then you may need to explicitly say which function you want in the .def file by specifying a mangled name using the entryname[=internalname] syntax. e.g.

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

B. An alternative to .def files is that you can export names "in place" using a #pragma.

#pragma comment(linker, "/export:Foo=_Foo@4")

C. A third alternative is to declare just one version of Foo as extern "C" to be exported unmangled. See here for details.