Why extern "C" still cannot remove name mangling in the following case - windows

extern "C"
{
__declspec(dllexport) LRESULT CALLBACK MTest
}
Using depends , I found there is still name mangling even using extern "C".

The only way to get truly undecorated names with __declspec(dllexport) is to export them with the __cdecl calling convention. CALLBACK becomes __stdcall, which decorates the "C" form of the name with a leading _ and trailing #bytes.
Otherwise you can use a .DEF file, which is a pain. Another MSVC specific way is to embed a /EXPORT directive into the object file (or pass it as a explicit linker setting)
#pragma comment(linker, "/EXPORT:ExportSymbol=DecoratedName");
For some reason the = part of the directive is not listed in the help

That's name decoration rather than mangling. You should declare the undecorated name in a DEF file and then you'll get the behaviour you are seeking.

Not being much of a visual C++ programmer the first thought that occurs to me is ... "do any of those macros LRESULT or CALLBACK introduce the standard calling convention?" Do the mangled names have #NUMBER_OF_BYTES_OF_PARAMATER_LIST or characters depicting the actual types appended to them?

Related

Error when including winuser.h. It defines ChangeMenu to ChangeMenuW or ChangeMenuA

Working on a Qt app on Windows. I include QVboxLayout in my source file only and this causes errors because its macro overwrites my method name.
foo.hpp
class foo
{
ChangeMenu();
}
foo.cpp
#include "foo.hpp"
#include "QVBoxLayout" // <--- this includes winuser.h
foo::ChangeMenu(){};
Now what happens is winuser.h has a macro
#ifdef UNICODE
#define ChangeMenu ChangeMenuW
#else
#define ChangeMenu ChangeMenuA
#endif // !UNICODE
This changes my function definition to ChangeMenuW but my declaration is still ChangeMenu.
How should I solve this? How can winuser.h define such a "normal" name as a macro?
Version of winuser.h is "windows kits\10\include\10.0.16299.0"
Pretty much any Windows API that deals with strings is actually a macro that resolves to a A or W version. There's no way around, you can either:
avoid including windows.h, but as you noticed, it creeps through;
brutally #undef the macro before defining/using your function; this is a fit punishment for hoarding such normal and non-macro-looking identifiers, but is tedious and some other code may actually need the Win32 function;
just accept it as a sad fact of life and avoid all the relevant Win32 APIs names; if you use Qt and follow its naming convention, it should be easy, as Qt functions use lowerCamelCase (as opposed to Win32 UpperCamelCase);
include windows.h explicitly straight in your header (possibly under an #ifdef _WIN32); this will make sure that your identifier will get replaced by the macro in all instances, so everything will work fine even if the compiler will actually compile a function with a different name; suitable for standalone projects, not suitable for libraries. (Thanks #Jonathan Potter for suggesting this)
You could take no care about this issue, Although your method name will be the same as the windows API, but the system will not mix them(just unify Unicode on both the place to define/call). If you call the ChangeMenu() directly, you will call the winapi, and if
foo f;
f.ChangeMenu();
or
foo::ChangeMenu();(static)
You will call your method.
And if you want to disable the winapi:
#ifdef ChangeMenu
#undef ChangeMenu
//code place that you define/call your own ChangeMenu().
#ifdef UNICODE
#define ChangeMenu ChangeMenuW
#else
#define ChangeMenu ChangeMenuA
#endif // !UNICODE
#endif
(It looks very tedious.)

How to specify a "clean" name of DLL exports?

I have defined a DLL-export as follows:
__declspec(dllexport)
DWORD WINAPI DllBootstrap(LPVOID addr) {
return 0;
}
Now, using DUMPBIN, the symbol is displayed as follows:
1 0 0001100A ?DllBootstrap##YGKPAX#Z = #ILT+5(?DllBootstrap##YGKPAX#Z)
And this is how the memory looks in Visual Studio:
ยก}....ReflectDLL.dll.?DllBootstrap##YGKPAX#Z..........................................
when inspecting PIMAGE_EXPORT_DIRECTORY.AddressOfNames.
What I need is a clean symbol, i.e., DUMPBIN should output something like:
1 0 0001100A DllBootstrap
and PIMAGE_EXPORT_DIRECTORY.AddressOfNames should point to:
DllBootstrap..........................................
How can I achieve this?
WIN32 BUILDS:
As #RbMm indicated, to retain your function name as-is and get no name decoration, you must use a .DEF file (and remove the __declspec(dllexport) specifier). Then create a DEF file with the line below and either specify it with the /DEF linker option or add it to your Visual Studio project and it will be picked up automatically by the linker:
EXPORTS DllBootstrap
If you don't want to deal with an external .DEF file and you will be using the Visual C++ compiler, the simplest way to limit decoration using just code is to declare your function with 'extern "C"'. This results in decoration including a preceding underscore and appends an "#" along with the argument's byte count in decimal. The following code for example:
extern "C" __declspec(dllexport)
DWORD WINAPI DllBootstrap(LPVOID addr) {
return 0;
}
produces an exported name of:
_DllBootstrap#4
This is how stdcall functions are decorated when C++ name-mangling is disabled with 'extern "C"'. NOTE: WINAPI maps to __stdcall. Retaining 'extern "C"' and changing the convention to __cdecl, you won't get any decoration whatsoever, but module entrypoints should generally remain stdcall as you have it listed in your sample.
If you still want to avoid a .DEF file, there is one last hack you can employ. Add the following line to your code:
#pragma comment(linker,"/EXPORT:DllBootstrap=_DllBootstrap#4")
This will pass an argument to the linker creating a new undecorated name symbol which maps to the decorated name. This isn't very clean as the original name will still exist in your DLL, but you will get your clean exported name.
WIN64 BUILDS (UPDATE):
As Hans Passant commented, for anyone using the Visual C++ 64-bit compiler, there is only the 64-bit calling convention (stdcall, cdecl, etc. keywords are ignored). While C++ mangling will still occur under this compiler, no additional decoration is made to the exported names. In this case, 'extern "C"' would be enough when the sample is compiled as C++ code; if compiled as C, no modifications would be necessary.

What does this preprocessor line mean?

I am working on a project with the library ADOL-C (for automatic differentiation) using gcc. Right now I am trying to recompile the library to use the parallelization features however the make process does not working apparently due to some preprocessor stuff.
I think the problematic line is :
#define ADOLC_OPENMP_THREAD_NUMBER int ADOLC_threadNumber
However I could not find what it means. Does it make a link between two variables? Also ADOLC_threadNumber has not been declared before...
The preprocessor doesn't even know what a variable is. All that #define does is define a short(long?)hand for declaring a variable. I.e., if you type
ADOLC_OPENMP_THREAD_NUMBER;
It becomes
int ADOLC_threadNumber;
It's just a text substitution. Everywhere in code where ADOLC_OPENMP_THREAD_NUMBER appears, it's substituted by int ADOLC_threadNumber.
As far as I see it, the line with the define itself is not problematic, but maybe the subsequent appearance of ADOLC_OPENMP_THREAD_NUMBER. However, to check this, we need to know more about the context.
#define is a directive used often in .h files,
it creates a macro, which is the association of an identifier or parameterized identifier with a token string.
After the macro is defined, the compiler can substitute the token string for each occurrence of the identifier in the source file.
#define may be associated with #ifndef directive to avoid to delare the identifier more than once :
#ifndef ADOLC_OPENMP_THREAD_NUMBER
#define ADOLC_OPENMP_THREAD_NUMBER int ADOLC_threadNumber
#endif

Do I have to specify extern "C" when exporting symbols?

I am wondering if extern "C" is a must or not?
Only if you want to call your code from C (or a different C++ compiler, which you should treat like C).
It is to disable name-mangling.
See this article on the C++ FAQ: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
No, you use extern "C" to provide a C-linkage to your C++ functions, so they won't be 'decorated' like normal C++ functions and to allow them to be called from C (or Objective-C).
Function decoration is used to implement the C++ function overloading feature and gives each variation of the function a different signature while allowing the developer to use the name he assigned.
Your C++ functions will be exported automatically by simply not using the static keyword. However if you have implemented your C++ functions within a Windows DLL it's necessary to use the declspec dllexport/dllimport keywords to access them externally.
Use of extern "C" switches off name mangling. If you don't do this you may make if hard for a client of your DLL to import your symbols.
Remember that different C++ compilers have different name mangling rules and so your mangled exported names may differ from the names used on import.
However, since it is wrong to import a class from a DLL if you are using a different compiler than that used for the DLL, this is rather a moot point.
So, if you are exporting classes (usually a bad idea anyway) it is easier to leave mangling on. Otherwise switch it off with extern "C".

Creating a DLL, confusion with __declspec(dllexport)

Visual Studio C++ 2005
Windows XP
I am creating this DLL library. The DLL actually links with another LIB. I have included the headers and lib path. Everything compiles ok.
Actually, this code I wrote for running on linux, which runs ok. Now I am porting it to run on windows.
However, I have noticed that some DLL from some code samples use this in there header file:
static __declspec(dllexport) float some_function(int num1, int num2);
However, I have done the following, sample code below for the header *.h file. However, not sure if I still need the above or not?
#ifdef __cplusplus
extern "C" {
#endif
media_t* get_media(media_description_t* obj);
void* get_item(media_description_list_t *obj, int num);
int get_number_format(media_t *obj);
const char* get_media_value(media_t *obj);
#ifdef __cplusplus
}
#endif
Sample code for for implementation *.cpp file
int get_number_format(media_t *obj)
{
Media *med = (Media*)obj;
return med->getNumFormat();
}
So, do I need this static __declspec(dllexport)?
Many thanks for any advice,
The linker needs to be told which of your functions should be exported, making them usable by other code that uses your DLL. __declspec(dllexport) does this. But you can also do it by providing the linker with a .def file, a list of exported function names. Somewhat painful because it now is up to you to keep that file in sync with your code. Docs are here.
__declspec(dllexport) adds the function to the DLL's export table. This table is a convention that allows a process wishing to use the DLL to correctly call the function.
There are other ways to export functions from DLLs, but this one is probably the more modern and easier to use.
yes it is needed, if you don't have the dllexport the function will not be accessible in any other application where you are calling that function.
If you put the implementation of a method in the h file, you don't need to use the __declspec(dllexport) declaration.

Resources