Specify ordinals of C++ exported functions in a DLL - c++

I am writing a DLL with mixed C/C++ code. I want to specify the ordinals of the functions I'm exporting. So I created a .DEF file that looks like this
LIBRARY LEONMATH
EXPORTS
sca_alloc #1
vec_alloc #2
mat_alloc #3
sca_free #4
vec_free #5
mat_free #6
...
I would like to specify the ordinals of my C++ functions and class methods too. I have tried using the Dependency Walker to add the mangled names of my functions to the .DEF file:
??0CScalar##QAE#XZ #25
??0CScalar##QAE#O#Z #26
??0CScalar##QAE#ABV0##Z #27
??1CScalar##QAE#XZ #28
But this has failed. Any ideas why this could be happening?
EDIT: kauppi made a good observation, so I'm adding more information to the question.
Platform: Windows (and I'm not interested in portability)
Compiler: Microsoft's C++ compiler (I'm using VS2005)
Why I want to do this?: Using the ordinals has the advantage of letting me call exported C++ functions from C code.

Well, I don't have experience with ordinals (which look like some ugly, compiler-specific thing), but I can help you with making C++/C code compatible.
Suppose, in C++, that your header file looks like this:
class MyClass
{
void foo(int);
int bar(int);
double bar(double);
void baz(MyClass);
};
You can make it C-compatible by doing the following:
#ifdef __cplusplus
#define EXTERN_C extern "C"
// Class definition here; unchanged
#else
#define EXTERN_C
typedef struct MyClass MyClass;
#endif
EXTERN_C void MyClass_foo (MyClass*, int);
EXTERN_C int MyClass_bar_int (MyClass*, int);
EXTERN_C double MyClass_bar_double (MyClass*, double);
EXTERN_C void MyClass_baz (MyClass*, MyClass*);
In the C++ source file, you just define the various extern "C" functions to pass to the desired member functions, like this (this is only one; the rest work similarly)
extern "C" void MyClass_foo (MyClass* obj, int i)
{
obj->foo(i);
}
The code will then have a C interface, without having to change the C++ code at all (except for declarations in the header; but those could also be moved to another file "myclass_c.h" or the like). All the functions declared/defined extern "C" won't be mangled, so you can do other operations on them easily. You will also probably want functions to construct/destroy instances of MyClass (you can, of course, use new/delete for this).

You said "Using the ordinals has the advantage of letting me call exported C++ functions from C code." , I am sorry to say that this is incorrect.
C++ class member functions have special calling convention which requires an invisible this value passed in an implementation-specific register/parameter. And also you need a class instance to pass, which you can not accomplish in C.
The only 2 uses of this that I know, are faster dynamic linking of the DLL and smaller Import Table. Just inspect mfc70.dll in system32 directory with the dependancy walker.

Related

What is the best way to construct a class object in a C++ DLL in a way that it is accessible from within any exported function of DLL?

If we have a C++ DLL with 4 exported functions, what is the best way to construct an object of a class when the DLL is loaded (by LoadLibrary), in a way that we can access public methods of that class from within any exported function (exported by extern "C" __declspec(dllexport)). I remember global stuff is evil.
Looking for a better way of doing the following (the following is not the best approach):
namespace namespace_top_of_CMS_DLL{
CMS CMS_Object =CMS();
CMS*CMS_Ptr_Object =&CMS_Object;
}
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runFullStructure(){
namespace_top_of_CMS_DLL::CMS_Ptr_Object->runFullStructure();
}
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runSubStructures(){
namespace_top_of_CMS_DLL::CMS_Ptr_Object->runSubStructures();
}
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runReducedStructure(){
namespace_top_of_CMS_DLL::CMS_Ptr_Object->runReducedStructure();
}
First of all, don't use absolute statements like "globals are evil". What is a global anyway? Even globals have some scope. If that scope makes logical sense, then it's certainly not evil. main is not evil, for example. An exported DLL function is similarly a "global". If you need to interact with that module, you're going to need some kind of way to access it.
You'll need to export at least 1 function from the DLL to use it, and use GetProcAddress. From there, you have any number of patterns to follow. The simplest is to just export C-style functions as you need them.
If you need C++ objects, DLLs can create a huge amount of headaches. I would recommend either exporting everything as C-style, or using COM.
"Looking for a better way of doing the following (the following is not the best approach): ..."
I'd prefer to put the global class instances into an unnamed namespace in the translation unit where your exported functions are implemented.
Remove the declarations for CMS CMS_Object and CMS*CMS_Ptr_Object from the header file. Also have a separate translation unit for the implementation, and move the inline definitions of your exxported functions there
Header:
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runFullStructure();
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runSubStructures();
extern "C" __declspec(dllexport)
void OPS_CMS_DLL_runReducedStructure();
Implementation
namespace { // << note no namespace here
CMS CMS_Object =CMS();
CMS*CMS_Ptr_Object =&CMS_Object;
}
void OPS_CMS_DLL_runFullStructure(){
CMS_Ptr_Object->runFullStructure();
}
void OPS_CMS_DLL_runSubStructures(){
CMS_Ptr_Object->runSubStructures();
}
void OPS_CMS_DLL_runReducedStructure(){
CMS_Ptr_Object->runReducedStructure();
}
That way you can ensure, they can be accessed from your exported function implementations exclusively.
"I remember global stuff are evil."
It's true that global variables are an indication for bad design in most cases. These are prone to clutter code, and being unintentionally used from other code, which is out of your control.
Having module private globals is perfectly OK.
Be careful about exposing a class outside a dll. The C ABI is far simpler and far better defined than the complex C++ ABI. If templates are involved all guarantees go out the window.
So unless you want to commit to always using the same toolchain to compile your dll and exe, stick to your extern "C" __declspec(dllexport) method in your OP. For convenience you can always provide a C++ wrapper (header only).

When is "extern C " necessary in c++ in windows?

As we know that we can use c functions directly in c++, when is extern "C" necessary then?
If your function is implemented in a .c file, the .cpp files will need the extern "C" reference, or else they'd reference a mangled C++-style function name, and the link would fail.
It's also handy for exporting functions from DLLs so that they are exported with a non-mangled name.
It's necessary when a C++ function must be called by C code rather than C++ code.
Basically, when you want your C++ library to be backwards compatible.
There are two rather different uses for extern "C". One is to define a function in C++ that you should be able to call from C. I.e., you're writing code in C++, but it needs to interface with C code. In this case, you define the function as extern "C":
extern "C" {
int c_callable_func1() {}
int c_callable_func2() {}
}
When you do this, the interface of those functions must follow pretty much the same rules as they would in C as well (e.g., you can't overload the functions or use default values for any parameters).
The other (considerably more common) situation is that you have code written in C that you want to be able to call from C++. In this case, the function definitions remain exactly as before, but the functions need to be declared/prototyped as extern "C". In a typical case, you want to use a single header that can be #included in either a C or C++ file, so the structure looks something like this:
// myheader.h
#ifndef MY_HEADER_H_INCLUDED_
#define MY_HEADER_H_INCLUDED_
#ifdef __cplusplus
extern "C" {
#endif
int func1(void);
void func2(int);
#ifdef __cplusplus
}
#endif
#endif
So, a C++ compiler will see function declarations (and typedefs, etc.) surrounded by an extern "C" block, while a C compiler will see prototypes, not surrounded by something it doesn't recognize.
In the first case (C++ functions callable from C), you'll normally structure the header roughly the same way, so you can also call those functions from C++ if necessary (but at the interface, you still lose all extra features of C++ like function overloading).
As you know that c++ support function overloading, which define the same function or method many times with different parameters. To do this, the compiler has to add some part of symbols for each one ... for example, the compiler will change the function name foo in the following declaration
from
void foo(int f,char c);
to
foo#i&c
Unfortunately, C doesn't support this. All function names remain the same after compiling it. So, to call a c++ function from c, you have to know the exact name after the modification and I think it's hard and different from a compiler to another.
to work around this and be able call c++ function from c and stop the compiler from changing the names you have to use this keyword like
extern "C" {
void foo(int f,char c);
}
that's it !!!
Because the function signatures generated by C and C++ compilers differ -- this sets up the C convention for C function even when using C++.

better understanding of extern "C" functions

I am just trying to further understand extern C functions.
According to my knowledge, an extern C function is always a function you are trying call from an application that has already been compiled. Either a executable, static or dynamic library.
extern "C"
{
HRESULT CreateDevice();
typedef HRESULT (*CREATEDEVICE)();
HRESULT ReleaseDevice();
typedef HRESULT (*RELEASEDEVICE)();
}
So my question is...
Is my understanding correct ??
Does it always have to be a C function pointer ??'
Why must you use a typedef for each function ??
I presume that when you use the GetProcAddress(). You are allocating memory on that particulars applications HEAP and not the one you are calling it from. Therefore you must release it from that heap as well ??
extern "C" has 2 implications. First, it declares that the symbolic names of the functions are not "name mangled" to support C++. Second, it tells the compiler that the function is called using the C calling convention rather than the PASCAL calling convention. The difference has to do with when the return address is pushed on the stack. Using the wrong calling convention will crash your app.
This declaration is for the compiler, not the linker. So the extern C function could exist in your own modules or in a binary library: the source of actual bytes for the function implementation are resolved by the linker. If the function signature is declared as a regular C++ function and not extern C, the compiler will mangle the symbolic name to encode type information from the function signature. This will make it incompatible with object code generated by other C++ compilers. Therefore creating an extern C function allows you to share code between compilers in binary form. Note that you can't expose member functions this way, only old-style C functions.
It doesn't have to be a function pointer. You can specify the function declaration normally and prefix it with extern "C", as shown in some Microsoft examples.
If you use GetProcAddress() you are not allocating any memory. You simply get the memory address of the function inside the DLL that has already been loaded into memory (with LoadLibrary(), presumably).
Even when using function pointers (such as those returned by GetProcAddress) you don't have to use typedef, it's just that the code looks pretty ugly without it. It's always hard to figure out what to write as well. I think it would be something like:
void (*pReleaseDevice)() = (void (__cdecl *)(void))GetProcAddress(hInstance, "ReleaseDevice");
extern "C" {} is a C++ convention to declare that the enclosed functions are C functions -- not C++ functions. C++ has a slightly different naming convention which conflicts with C. If you have a library written in C and want to use it in a C++ program, you have to use extern "C" {} to let the compiler know these are C functions. If the library was written in C++ I believe the extern "C" {} will cause an error.
Note that extern has multiple meanings -- this specific case is a C++ convention and is unrelated to different uses of extern. For example,
extern int count;
has a completely different meaning than extern "C" {}.
The typedef is separate from the extern "C" {} issue. typedefs let you create aliases for common types that make more sense. For example, declaring structs is often a verbose process. I can use a typedef to shorten it:
struct mystruct {int a; int b};
typedef struct mystruct returncode;
// I can now declare a variable as type 'returncode'
returncode a;
Thus, in your example the HRESULT is really an alias for (*CREATEDEVICE)() although I believe you have to put it before the function (and not after).
One important aspect of specifying extern "C" linkage is that the function names do not get mangled, which is the default for C++ names.
In order for your library's functions to be able to be loaded using GetProcAddress, you need to either add the function to the .def file, use __declspec(dllexport) or use extern "C".
To answer, in order:
extern "C" functions are used for interop with C from C++. Using them has the consequence that C code can call the function. As the windows API is a C API all functions are extern "C" to ensure that C and C++ code can make use of the API.
In order for c++ programs to interoperate with other languages, including C, as a convention , functions are exported using extern "C". Which is why a lot of dll code does this. It is not a technical requirement however.
So no, it does NOT have to be a C function pointer.
You don't have to use typedef's either.
The example code provided is from a header file that is publishing the exports of a DLL twice - Once as the set of extern "C" methods that are exported so that the dll can be statically linked. the other as a set of function pointer types, so that the dll can be dynamically loaded, and the function pointer types used with GetProcAddress.

C++ DLL Export: Decorated/Mangled names

Created basic C++ DLL and exported names using Module Definition file (MyDLL.def).
After compilation I check the exported function names using dumpbin.exe
I expect to see:
SomeFunction
but I see this instead:
SomeFunction = SomeFunction###23mangledstuff#####
Why?
The exported function appears undecorated (especially compared to not using the Module Def file), but what's up with the other stuff?
If I use dumpbin.exe against a DLL from any commercial application, you get the clean:
SomeFunction
and nothing else...
I also tried removing the Module Definition and exporting the names using the "C" style of export, namely:
extern "C" void __declspec(dllexport) SomeFunction();
(Simply using "extern "C" did not create an exported function)
However, this still creates the same output, namely:
SomeFunction = SomeFunction###23mangledstuff#####
I also tried the #define dllexport __declspec(dllexport) option and created a LIB with no problem. However, I don't want to have to provide a LIB file to people using the DLL in their C# application.
It's a plain vanilla C++ DLL (unmanaged code), compiled with C++ nothing but a simple header and code. Without Module Def I get mangled exported functions (I can create a static library and use the LIB no problem. I'm trying to avoid that). If I use extern "C" __declspec(dllexport) OR a Module Definition I get what appears to be an undecorated function name... the only problem is that it is followed by an "=" and what looks like a decorated version of the function. I want to get rid of the stuff after the "=" - or at least understand why it is there.
As it stands, I'm pretty certain that I can call the function from C# using a P/Invoke... I just want to avoid that junk at the end of the "=".
I'm open to suggestions on how to change the project/compiler settings, but I just used the standard Visual Studio DLL template - nothing special.
Instead of using .def file just insert pragma comment like this
#pragma comment(linker, "/EXPORT:SomeFunction=_SomeFunction###23mangledstuff#####")
Edit: Or even easier: Inside the body of the function use
#pragma comment(linker, "/EXPORT:" __FUNCTION__"=" __FUNCDNAME__)
. . . if you have troubles finding the decorated function name. This last pragma can be further reduced with a simple macro definition.
You can get what you want by turning off debug info generation. Project + Properties, Linker, Debugging, Generate Debug Info = No.
Naturally, you only want to do this for the Release build. Where the option is already set that way.
You have to declare the functions as extern "C" if you don't want their names to be mangled.
From experience, be careful if you use __stdcall in your function signature. With __stdcall, the name will remain mangled to some extent (you will find out quickly enough). Apparently, there are two levels of mangling, one the extern "C" deals with at the C++ level, but it does not deal with another level of name mangling caused by __stdcall. The extra mangling is apparently relevant to overloading -- but I am not certain of that.
Even without the mangling, the 32-bit and 64-bit builds name exports differently, even with extern "C". Check it out with DEPENDS.EXE.
This can mean BIG trouble to any client that does a LoadLibrary+GetProcAdress to access your function.
So, on top of all the others use a Module Definition File as follows:
LIBRARY MYDLL
EXPORTS
myFunction=myFunction
Yeap, it's a bit of a pain to maintain, but then how many exported functions do you write a day?
Moreover, I usually change the macros like shown below, since my DLLs export functions not C++ classes and I want them to be callable by most programming environments:
#ifdef WTS_EXPORTS
#define WTS_API(ReturnType) extern "C" __declspec(dllexport) ReturnType WINAPI
#else
#define WTS_API(ReturnType) extern "C" __declspec(dllimport) ReturnType WINAPI
#endif
WTS_API(int) fnWTS(void);
The last line used to confuse VisualAssistX a couple of years ago, I don't know if it properly digests it now :-)
Sorry for replying to an old thread, but what has been marked as the answer did not work for me.
As a number of people have pointed out, the extern "C" decoration is important. Changing the "Project / Properties / Linker / Debugging / Generate debug info" setting made absolutely no difference to the mangled names being generated for me in either Debug or Release build mode.
Setup: VS2005 compiling a Visual C++ Class Library project. I was checking the compiled .dll output with Microsoft's Dependency Walker tool.
Here is an example recipe that worked for me...
In project.h:
#define DllExport extern "C" __declspec( dllexport )
DllExport bool API_Init();
DllExport bool API_Shutdown();
In project.cpp:
#include "project.h"
bool API_Init()
{
return true;
}
bool API_Shutdown()
{
return true;
}
Then being called from C# managed code, class.cs:
using System.Runtime.Interopservices;
namespace Foo
{
public class Project
{
[DllImport("project.dll")]
public static extern bool API_Init();
[DllImport("project.dll")]
public static extern bool API_Shutdown();
}
}
Doing the above prevented the mangled names in both Debug and Release mode, regardless of the Generate debug info setting. Good luck.
I know how many times I've tried forcing function names using code and #pragma's.
And I always end with exactly same thing, using Module-Definition File (*.def) at the end.
And here is the reason:
//---------------------------------------------------------------------------------------------------
// Test cases built using VC2010 - Win32 - Debug / Release << doesn't matter
//---------------------------------------------------------------------------------------------------
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = Yes (/DEBUG)
// || (or, also doesn't matter)
// SET: Project > Properties > Linker > Debugging > Generate Debug Info = No + delete PDB file!
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> _SetCallback#4
__declspec(dllexport) void SetCallback(LPCALLBACK function);
> ?SetCallback##YAXP6AXHPADPAX#Z#Z
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> ?SetCallback##YGXP6GXHPADPAX#Z#Z
//---------------------------------------------------------------------------------------------------
// this also big is nonsense cause as soon you change your calling convention or add / remove
// extern "C" code won't link anymore.
// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
// doesn't work on other cases
#pragma comment(linker, "/EXPORT:SetCallback=SetCallback")
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=_SetCallback#4")
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback##YAXP6AXHPADPAX#Z#Z")
__declspec(dllexport) void SetCallback(LPCALLBACK function);
// doesn't work on other cases / creates alias
#pragma comment(linker, "/EXPORT:SetCallback=?SetCallback##YGXP6GXHPADPAX#Z#Z")
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
//---------------------------------------------------------------------------------------------------
// So far only repetable case is using Module-Definition File (*.def) in all possible cases:
EXPORTS
SetCallback
extern "C" __declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback
extern "C" __declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback
__declspec(dllexport) void SetCallback(LPCALLBACK function);
> SetCallback
__declspec(dllexport) void __stdcall SetCallback(LPCALLBACK function);
> SetCallback
// And by far this is most acceptable as it will reproduce exactly same exported function name
// using most common compilers. Header is dictating calling convention so not much trouble for
// other sw/ppl trying to build Interop or similar.
I wonder why no one did this, it took me only 10 mins to test all cases.
the SomeFunction###23mangledstuff##### is mangled to give the types and class of the C++ function. The simple exports are functions that are callable from C i.e. are written in C or else are declared extern "C' in C++ code. If is you want a simple interface you have to make the functions you export be use just C types and make them non member functions in the global namespace.
Basically, when you use functions in C++, parts of their names now include their signature and suchlike, in order to facilitate language features like overloading.
If you write a DLL using __declspec(dllexport), then it should also produce a lib. Link to that lib, and you will automatically be linked and the functions registered by the CRT at start-up time (if you remembered to change all your imports to exports). You don't need to know about name mangling if you use this system.
In case it wasn't clear from the hundreds of lines of waffle on the subject of mangled exports. Here's my 2c worth :)
After creating a project called Win32Project2 using VS 2012 and choosing export all symbols in the wizard. You should have 2 files called Win32Project2.cpp and Win32project2.h
Both of those will reference an example exportable variable and an example exported function.
In Win32Project2.h you will have the following:
#ifdef WIN32PROJECT2_EXPORTS
#define WIN32PROJECT2_API __declspec(dllexport)
#else
#define WIN32PROJECT2_API __declspec(dllimport)
#endif
extern WIN32PROJECT2_API int nWin32Project2;
WIN32PROJECT2_API int fnWin32Project2(void);
To unmangle CHANGE the last two lines to extern "C" declarations to:
extern "C" WIN32PROJECT2_API int nWin32Project2;
extern "C" WIN32PROJECT2_API int fnWin32Project2(void);
In Win32Project2.cpp you will also have the following default definitions:
// This is an example of an exported variable
WIN32PROJECT2_API int nWin32Project2=0;
// This is an example of an exported function.
WIN32PROJECT2_API int fnWin32Project2(void)
{
return 42;
}
To unmangle CHANGE THESE TO:
// This is an example of an exported variable
extern "C" WIN32PROJECT2_API int nWin32Project2=0;
// This is an example of an exported function.
extern "C" WIN32PROJECT2_API int fnWin32Project2(void)
{
return 42;
}
Essentially you must use the extern "C" prefix in front of declarations in order to force the linker to produce unmangled C like names.
If you prefer to use mangled names for that bit of extra obfuscation (in case the mangling info is useful to someone somehow) use "dumpbin /exports Win32Project2.dll" from a VC command line to lookup the actual reference names. It will have the form "?fnWind32Project2#[param bytes]#[other info] . There are also other DLL viewing tools around if running a VC command shell doesn't float your boat.
Exactly why MS doesn't default to this convention is a mystery. The actual mangling information means something (like parameter size in bytes and more) which might be useful for validation and debugging but is otherwise guff.
To import the DLL function above into C# project (in this case a basic C# windows application with a form on it containing the button "button1") here's some sample code:
using System.Runtime.InteropServices;
namespace AudioRecApp
{
public partial class Form1 : Form
{
[ DllImport("c:\\Projects\test\Debug\Win32Projects2.dll")]
public static extern int fnWin32Project2();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int value;
value = fnWin32Project2();
}
}
}

Overloaded functions in C++ DLL def file

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.
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.
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!
I had a similar issue so I wanted to post on this as well.
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.
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.
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.
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.
Systax for EXPORTS definition is:
entryname[=internalname] [#ordinal [NONAME]] [PRIVATE] [DATA]
entryname is the function or variable name that you want to export. This is required. If the name you export is different from the name in the DLL, specify the export's name in the DLL with internalname.
For example, if your DLL exports a function, func1() and you want it to be used as func2(), you would specify:
EXPORTS
func2=func1
Just see the mangled names (using Dependency walker) and specify your own functions name.
Source: http://msdn.microsoft.com/en-us/library/hyx1zcd3(v=vs.71).aspx
Edit: This works for dynamic DLLs, where we need to use GetProcAddress() to explicitly fetch a functions in Dll.