I have a library (C++) which has some API functions. One of them is declared as __cdecl, but gets a function poiner from __stdcall. Something like:
typedef int (__stdcall *Func)(unsigned char* buffer);
//...
int ApiFunc(Func funcPtr); //This is __cdecl since it is an 'extern "C"' library and the calling convention is not specified
Then - I have a C++ executable project which uses this library, but doesn't call the above API or uses the Func type.
After changing the calling convention of Func to __stdcall, I get the following compilation error:
error C2995:
'std::pointer_to_unary_function<_Arg,_Result,_Result(__cdecl *)(_Arg)> std::ptr_fun(_Result (__cdecl *)(_Arg))' : function
template has already been
defined c:\program files\microsoft
visual studio 8\vc\include\functional
Any idea what could it be?
Thanks in advance!!
Err.. they're incompatible. You have to specify the same calling convention on both sides of the call. Otherwise attempting to call will blow up the machine stack.
They ARE compatible, in Windows at least (and in Linux there isn't __stdcall at all...)
The problem was that by mistake, the library re-defined __stdcall for compatibility with Linux, as:
#ifndef __MYLIB_WIN32
//Just an empty define for Linux compilation
#define __stdcall
#endif
The exe project includes this definition, and __MYLIB_WIN32 was not defined in it, but in the library only.
Changing the above definition to:
#ifndef WIN32
//Just an empty define for Linux compilation
#define __stdcall
#endif
and everything works fine.
Thank you all.
Related
I have a C/C++ VS compiled Dll and a Delphi library created from a C/C++ h-file. The h-file has macro defined directives. Included in all the C/C++ external and typedef calls have a directive DISPLAY_CALL included.
On conversion to Delphi, I excluded the DISPLAY_CALL directive as it did not fit with my Delphi conversion, The bulk of the DLL functions work perfectly except for certain functions and type calls where the DLL makes use of the DISPLAY_CALL directive to determine if it is a windows platform or not and will return an error if called in another platform (ignored within the DLL). However if the DISPLAY_CALL is excluded then an error is received on any platform so the DISPLAY_CALL directive needs to be received by the DLL. Compiling the C++ with Visual Studio confirms this error if excluding the DISPLAY_CALL directive.
I am using Tokyo 10.2.3 Enterprise.
I have searched on how to do this without any success.
So how do you include this DISPLAY_CALL directive into the Delphi external calling process. I have come accross dependency but I am unsure if this is the correct direction to take.
Below is an extract of both the C/C++ Code and then the current translated Delphi Code.
C/C++ code
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
#define DISPLAY_CALL WINAPI
#else
#define DISPLAY_CALL
#endif
#ifdef __cplusplus
extern "C"{
#endif
typedef void (DISPLAY_CALL *display_removed_cb)(int fd, void *user_data);
int DISPLAY_CALL display_get_device(display_device_handle *dev_handle);
Delphi code
const
DisplayName = 'display.dll'; //defined for windows stdcall
type
display_removed_cb = procedure(fd:integer; user_data:pointer);
function display_get_device (dev_handle:pdisplay_device_handle): integer; stdcall; external DisplayName name 'display_get_device';
I look forward to some superior knowledge on this.
In effect, the C++ code is saying that stdcall is to be used on Windows, and the default calling convention (invariably cdecl) elsewhere.
Your question has a long spiel about what you think DISPLAY_CALL is used for that I'm afraid I cannot make any sense of. I think you are over thinking this and getting a little confused. It really is nothing more than a calling convention specification.
So, in your Delphi code, you should do something like this:
function display_get_device(dev_handle:pdisplay_device_handle): integer;
{$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
external DisplayName name 'display_get_device';
This assumes you wish to support platforms other than Windows. If not, and you only support Windows, then you can simply use stdcall unconditionally.
You must also specify the calling convention everywhere, and your Delphi code fails to do so. You missed it on the callback type. This should be:
type
display_removed_cb = procedure(fd:integer; user_data:pointer);
{$IFDEF MSWINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
And obviously whenever you declare a function that will be passed as an display_removed_cb argument, you must also specify the appropriate calling convention.
I am using clang power tools to compile a project which is usually compiled using visual studio.
In boost's lwm_win32.hpp header (yes we are using an old version of boost and currently cannot update) I get an error reading.
function declared stdcall here was previously declared without calling convention
the line in question is:
extern "C" __declspec(dllimport) long __stdcall InterlockedExchange(long volatile *, long);
I don't get any errors or warnings for this line when compiling with visual studio. Interestingly I don't get any even if I manually change the calling convention from __stdcall to __cdecl.
Clang tells me which previous declaration it has seen. By manually inspecting this location I would say clang is right. After deciphering all preprocessor defines I would also say __cdecl is what should be seen by visual studio. However, neither the official documentation for InterlockedExchange, nor the official documentation for the intrinsic do mention a specific calling convention.
So basically I am unsure what the root of the problem is. Visual studio accepting any calling convention in the declaration? Clang not seeing the correct declaration due to some preprocessor macros set to the wrong value? Boost declaring the wrong calling convention? I must admit I am confused.
Visual Studio version is 2015 Update 3.
Clang++ version is 6.0.0 called with parameter -fms-compatibility-version=19.
EDIT
As suggested in the comments I had a look at the preprocessor output of MSVC and Clang. They looked rather identical to me. For both the line from boost expands to
extern "C" __declspec(dllimport) long __stdcall _InterlockedExchange(long volatile *, long);
Both have
#pragma intrinsic(_InterlockedExchange)
and the declarations
long __cdecl _InterlockedExchange(long volatile * _Target, long _Value);
LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value);
as well as several inline implementations for different overloads.
In both compilers I target 32-bit (-m32 for clang).
Do the clang power tools offer you things that you really don't want to live without?
If not (and I imagine that is a big if) then you might consider experimenting with VS 2017's support for clang. I have no experience of it personally and it's all still a bit new but what I do know is that MS are putting a lot of work in and it may well pay off in the long run.
As it is, I think you might be out on a bit of a limb. And whatever should and should not be in the header files, I would say that what MS say goes, wouldn't you?
Why are you stuck with that old version of boost? That might be a blocking issue here.
after reading and learning for years on this great platform its my first post now.
My Problem:
In C++ I am trying to create a dynamic linked library (32 bit) that will serve as a AQMP Communication Client (based on SimpleAmqpClient). The dll file will then be used inside a third party application (32 bit).
During my tests where I invoke the dll in a custom executable everything works fine. But when I try to use the dll in the third party application I get an access violation error (0x00000000). I found out that the problem may be the function calling convention.
With the few code lines presented below that error can be reproduced. It disappears if I remove the __stdcall expression in mytest.dll. Normally I would expect the code to work because it uses the same calling convention in custom_test.exe and mytest.dll.
(Sidenote: the third party application expects a __stdcall function thats why I rely on it)
I would like to understand this behavior. Thanks in advance!
My Setup:
OS: Windows 7
32 bit Compiler: gcc 5.3 (Cygwin)
My Code (custom_test.exe):
#include <stdio.h>
#include <windows.h>
int main(void) {
HINSTANCE hInstance;
hInstance=LoadLibrary("mytest.dll");
FARPROC lpfnGetProcessID = GetProcAddress(HMODULE(hInstance), "test");
// Function prototype
typedef void (__stdcall *myFunction)(void);
myFunction test;
test = myFunction(lpfnGetProcessID);
// Call Function
test();
FreeLibrary(hInstance);
}
My Code (mytest.dll):
extern "C" __declspec(dllexport) void __stdcall test(void) {
printf("Inside Function \n");
}
I compile the code via
dll: g++ mytest.cpp -o mytest.dll -shared -std=gnu++11
exe: g++ custom_test.cpp -o custom_test.exe -std=gnu++11
The __stdcall convention makes it the responsibility of the called function to clean up the stack on return, while __cdecl makes it the caller's responsibility.
We can't see the actual declaration in the third-party DLL, but my initial assumption would be that the DLL expects arguments and is either using what it believes to be stack arguments in error, or is cleaning up the stack based on it's assumption of the stack arguments and generally messing with your stack.
EDIT
In this instance though, I see that when compiling in 32 bit, the test function is exported with a name of 'test#0'. If you change your GetProcAddress to use this decorated name instead it will work.
Ok now several hours later I can see clear again! Thx IanM_Matrix1 for the suggestion, the so called name decoration was indeed the point.
After my research I can now share some helpful ressources I found:
It is important to know that some compilers add different decorations to the function names, see here:
http://wyw.dcweb.cn/stdcall.htm
With that in mind one can read this page about Win32 calling conventions in general:
http://www.unixwiz.net/techtips/win32-callconv.html
When using gcc the decorations can also be disabled via the flag -Wl,--kill-at.
I have a library code which is written in VS 2003 , C++ 7.1
I managed to compile it in VS 2010. Now i need to compile it in VS2003 as well.
Problem is that i can not prevent VS2003 name mangling !
I used __declspec(dllexport) __stdcall before function name and i also put codes in extern "C" block.
I still get mangled function names when i compile it in VS 20003. I dont need a .def file when i use __declspec(dllexport) right?
hee is the code :
extern "C"
{
void __declspec(dllexport) __stdcall FreeMyObject(MyObjectHandle pObj)
{
delete pObj;
}
}
Also "Callin Convention" is __cdecl (/Gd)
Why i get mangled function names? is there any options i need to set in compiler option?
The keyword _stdcall, along with _cdecl, _thiscall, and others, are all calling conventions specifying how the compiler handles pushing and popping the arguments and the return value. Functions names made with _stdcall (at least in visual studio) are "decorated" when they are exported. If you want to find the exported name of the function, you can use the visual studio command line function DUMPBIN /EXPORTS "DLL file location". Your function name will probably look something like this: _FreeMyObject#(some number). You could also use a .def file and define the name yourself, but I personally think that is a pain.
I have an external library made using C code. I wish to call a function from the library in my c++ project. The original format of the function prototype was.
extern void butterThreeBp(real_T eml_dt, real_T eml_fl, real_T eml_fu, real_T eml_b3[7], real_T eml_a3[7]);
And this caused the following linker error in MSVC2008
error LNK2019: unresolved external symbol "void __cdecl butterThreeBp(double,double,double,double * const,double * const)" (?butterThreeBp##YAXNNNQAN0#Z) referenced in function "public: void __thiscall myThread::setDRNLc(double)" (?setDRNLc#myThread##QAEXN#Z)
I then changed this prototype to
extern "C" void ...
and then get the following error:
\butterThreeBp.lib : fatal error LNK1127: library is corrupt
I have rebuilt the library numerous times and am pretty certain that it is not corrupt. Any help would be great. Thanks!!
You do not have to use the included LCC compiler with MATLAB. The simplest solution is to get MATLAB to use VC++. http://www.mathworks.com/support/compilers/R2010b/index.html
IIRC you should add extern "C" only when compiling with C++ compiler.
Something like that:
#ifdef __cplusplus
extern "C" {
#endif
// the declarations
#ifdef __cplusplus
}
#endif
Got it! I generated the library code using the MATLAB embedded coder and was using Matlab's Lcc built in compiler to build the library. I am working on the main application in MSVC, therefore I guess there must have been some calling convention problem between the library (Lcc) and my main project (MSVC). This problem was particularly difficult to spot because one of my libraries (ButterOneLp) worked fine, even though it was generated using Lcc. However, another library did not work.
The problem was fixed by using the
mex -setup
. . . command in MATLAB and changing the default compiler to MSVC as opposed to the default Lcc.
I think that Lcc is based on gcc, so if anybody knows how to change the calling convention in the C++ code so that gcc/lcc libraries can be called from MSVC, that would be great. However, that is a whole different question to the original on posted.
The moral of this story is to check that your library and calling application are/were built using the same compiler if you get a "fatal error LNK1127: library is corrupt".