Cpp return curiosity - c++

A lot o functions in OpenNI return like this:
XN_C_API XnInt32 XN_C_DECL xnVersionCompare (const XnVersion *pVersion1, const XnVersion *pVersion2)
I'd like to now what is XN_C_API and XN_C_DECL.
Just curiosity!

It's not anything to do with the return value. Without looking at the source, I suspect that when compiling for Windows:
XN_C_API gets defined to either __declspec(dllexport) or __declspec(dllimport) depending on whether you're compiling the DLL or importing functions from it.
XN_C_DECL gets defined to the desired calling convention for the function (probably __stdcall or __cdecl)

Without having looked at the definitions, I'd guess:
XN_C_API is effectively extern "C" for a C++ compiler so that a C function can be called from C++.
XN_C_DECL deals with the calling conventions and export/import issues imposed by Windows. That might be __declspec(ddlexport) or __declspec(dllimport), and it might include __stdcall etc, and might also worry about FAR etc (but probably doesn't need to any more).

Related

Passing a VB6 boolean variable to an stdcall function in C++ DLL

I am looking for the most fool-safe way to pass a VB6 boolean variable to a function (written in C++, stdcall).
The C++ function will set the "bool" variable of a struct using this VB6 variable.
I have tried declaring it like this in C++:
extern "C" __declspec(dllexport) int SetParameter( BOOL bErrorView)
{
DLL_sSettings nSet;
nSet.bErrorView =(bErrorView != FALSE);
int ret = stSetParameter(sizeof(DLL_sSettings), nSet);
return (ret);
}
stSetParameter is declared as
extern "C" int ST_COMDLL_API stSetParameter(int DataLen, DLL_sSettings Settings);
The DLL_sSetting is declared as
typedef struct
{
bool bErrorView; // true: Show
// false: Don't show
(...)
} DLL_sSettings;
However, I am unable to get it to work.
I call it in VB6 using
Private Declare Function SetParameter Lib "MyDLL.dll" Alias "_SetParameter#4" (ByVal bErrorView As Boolean) As Long
But it does not work as expected, I guess somewhere the VB6 Boolean gets lost or is being incorrectly converted.
I am currently using VB6 Boolean, C++ BOOL and C++ bool.
I know that is not so nice, but I don't see any other way.
Does anybody spot something wrong in my code?
VB6 uses the StdCall calling convention by default (cdecl convention is supported if you create a type library with a module section describing your imports, instead of using Declare Function). And C++ supports a whole host of calling conventions: stdcall, fastcall, cdecl, thiscall.
It is important to note that calling functions using stdcall in another library is not enough to change your functions to stdcall. You can use a command-line switch to the compiler, but the most robust is to include the __stdcall keyword in your source code. It gets applied to the name of the function, like so:
int __stdcall functionname(int args);
Since you will also want to export those functions for VB6 to find them, you'll want extern "C" to reduce name mangling, and __declspec(dllexport) to place them in the exports table.
It's pretty common to use a macro to do all of the above at once. It looks like the library you are wrapping does this with ST_COMDLL_API. Inside the library, that will expand to __declspec(dllexport) __stdcall. For consumers, it will use dllimport instead.
Any time you are defining an API to be used across different compilers (or even different languages), it's a good idea to be very explicit about calling convention and structure packing (#pragma pack). Otherwise you are at the mercy of options specified in the project file and other headers files. Even if you are happy with the defaults the compiler uses, your public headers should be explicit, because eventually someone will try to use two libraries in the same program, and the other library may demand changes to the compile options.
BOOL is type definition for int.
it declared in windef.h as follows:
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
bool is C++ type, which can't be used in function prototype if you declare function with extern "C".
so VB should treat BOOL as Long (32 bit integer), not as Bolean. 0 means false otherwise (usually 1) it is true.

C++ Function Type?

I'm new to, and learning C++ (know a lot of Java) and the following code confuses me...
I know this code fragment is dealing with a pointer-to-function (it's a callback, that makes sense) but what is throwing me off is the argument between the return type and the function name. What the bloody hell is that?
It looks like a type of function, but I have never heard of that and even after searching and reading about pointer-to-functions I was not able to find anything mentioning that functions could have a type.
If this is true, how does one define a function type?
Thanks, -Cody
GLFWCALL is not a type, it's a macro which is expanded to a calling convention specific to the platform, or an empty string. Here's a trimmed fragment of glfw.h:
#if defined(_WIN32) && defined(GLFW_BUILD_DLL)
#define GLFWCALL __stdcall
#elif defined(_WIN32) && defined(GLFW_DLL)
#define GLFWCALL __stdcall
#else
/* We are either building/calling a static lib or we are non-win32 */
#define GLFWCALL
#endif
Using a correct calling convention is important on x86/win32, since some of them expect the stack to be cleaned by callee and others by the caller. There can also be differences in the order of passing the arguments.
On Windows, GLFWCALL is a macro for __stdcall, and on other platforms, it's a macro for nothing.
__stdcall implements a particular calling convention, and is a compiler extension on top of normal C or C++.
Macros are pieces of code that do replacements on your code before the lexer and parser of your compiler interact with them.
The GLFWCALL is a macro that can expand to a calling convention if one is needed. Because this function will be called by external code, it has to use the calling convention that external code expects. For example, if the function puts its return value on the stack and the external code expects it in a register, boom.
The question marked part of the function signature is a preprocessor macro that is defined somewhere else in the header. Certain features on certain platforms have extra requirements.
For example functions in DLL files on the Windows platform often make use of the __declspec(dllexport) modifier but when the same header is included in a user's project they need to use __declspec(dllimport). Using a preprocessor macro for that purpose means they can just use that macro on all relevant functions and simply define the macro differently when compiling their own DLL or a user's DLL and on platforms where __declspec is irrelevant it can be defined to nothing. There are many other reasons for macros like that one.
In this particular case you can effectively pretend that macro is blank and ignore it entirely.

Question about c++ naming conventions

I'm trying to create a abstraction layer for platforms such as win32, mac os, linux, iOs etc.
I want this to be dynamically linked. On platforms that don't support this it shouldn't be a problem since from what I've seen everything that can be compiled as a dynamic library can be compiled as a static one as well with minimum impact on the code.
Now, to get to the point of this:
I created a interface named IThread and a class named CThread. I use a function named CreateThread that's defined with extern "C" to be able to export it and call it outside the library. The problem here is that in win32 for example there already is a function named CreateThread and thus I get a linker error. I understand the error and why it's appearing but I'm not sure of a good way to avoid this. I don't really like to use weird naming as qt uses like CreateQtThread.
Another idea I have would be is to create a thread manager/factory that creates instances of CThread but I'm not sure this would be a great idea.
What do you guys think about this? I'm asking because I don't want to rush on important organizing problems like this.
Thank you very much
I use a function named CreateThread that's defined with extern "C" to be able to export it and call it outside the library.
This is bad. I can't talk for other platforms, but on windows it's perfectly fine to export C++ functions. They are just get mangled, and you get some sanity checking in case someone changes the declaration. In fact, it's the only correct way to export a function that is C++. If you declare it as extern "C" you get no namespaces, no overloading, and someone who compiles with /EHsc will be in trouble if an exception escapes from your function.
Preferred solution: Do not declare them as extern "C", and put them in a namespace.
The only other solution: well, guess why all those C libraries prefix their functions with their_lib_prefix_function...
Your decision to use extern "C" is sound in my view because it allows access from other languages, compilers etc. But doing so means you can't use namespaces so you simply must prefix your functions with something to identify them as being from your library, a poor man's namespace if you will.
This is the compromise you must make if you want to use extern "C".
Well, I don't know whether you will like this as I know the C developers I worked with found it unaesthetic. But, it's very simple and prevents collisions like this. (More or less mentioned in this answer with the "their_lib_prefix_function" comment.)
So, whenever I was using C code, I used to basically 'namespace' my functions using an underscore. So, let's say your namespace is MegaAbstraction, then something like CreateThread becomes MegaAbstraction_CreateThread. Easy peasy. And no collisions, unless someone else has a namespace called MegaAbstraction in which case I recommend finding a namespace that's unlikely to be used by anyone else. ;)
Does your CreateThread use the stdcall calling convention (aka WINAPI)? If you use the cdecl calling convention, it should export the function name as _CreateThread and avoid the linkage conflict with the Win32 CreateThread function.
extern "C" _declspec(export) int _cdecl CreateThread(...
There is no "CreateQtThread" function in Qt, not even something similar. There's a QThread class, and it has constructors. If needed, you can put everything in a namespace.

stdcall name mangling using extern c and dllexport vs module definitions (msvc++)

I was trying to export a simple test function for a dll to work with an application (fyi: mIRC) that specifies the calling convention as:
int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
Now, to call this from the application, I'd be using test_func but I have noticed due to name mangling it is not as simple as I'd thought.
Through similar topics here I have come to the understanding that using extern "C" in combination with __declspec(dllexport) is an equivelant (somewhat) method of removing mangling to module definitions (.def). However, when using the extern/dllexport method my function (as an example) is always _test_func#numbers whereas the .def removed all mangling as required for use with the application i needed to export to.
Could someone please explain why this is? I'm just curious about the two methods. Thanks!
extern "C" has nothing to do with stdcall: it only declares that C++ name mangling (aka type-safe linkage; inclusion of type information in symbol name) is disable. You need to use it independent of whether you use C calling convention or stdcall calling convention.
In stdcall calling convention, the callee removes the parameters from the stack. To make that safe, the exported name contains the number of bytes that the callee will remove from the stack.
If the application you are exporting to requires that no #number suffix is added to the name, it probably means that it expects C calling convention. So you should stop declaring the function as __stdcall. When you the declare it as declspec(dllexport), you should get an undecorated name in the DLL.
In the DEF file, you can call the function whatever you want; no additional checking is performed.
dllexport/import are designed to be loaded back by themselves, not an old C library using GetProcAddress. The mangling you have seen is what all Microsoft compilers have done for a long time for __stdcall functions. Most likely, your target either expects a __cdecl function, not __stdcall, but if not, you will need to use a .def file to specifically un-mangle the name.

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.