Adding an stdcall on a callback function gives an argument mismatch [GNU] - gnu

I'm trying to add an stdcall calling convention to my GNU compiled DLL.
Here is my code:
typedef void (__stdcall * CTMCashAcceptCallback) (
const struct CTMEventInfo,
const struct CTMAcceptEvent );
It's been called by this function:
LIBCTMCLIENT_FUNC void ctm_add_cash_accept_event_handler(CTMCashAcceptCallback);
where:
#define LIBCTMCLIENT_FUNC LIBCTMCLIENT_C_LINKAGE __declspec(dllexport) __stdcall
The problem is that it gives me this note:
note: expected 'CTMCashAcceptCallback' but argument is of type 'void (*)(const struct CTMEventInfo, const struct CTMAcceptEvent)'
When I remove the __stdcall or replace it with __cdecl instead, it does not give that information. Is it not possible to use stdcall when compiling through GNU or maybe I'm not doing it right?

The user code needs to explicitly tell the compiler its own function (the one you did not show) to be __stdcall, if that is what the DLL expects. Something like
__stdcall myCTMCashAccept (
const struct CTMEventInfo,
const struct CTMAcceptEvent)
{
//...
}
// ...
ctm_add_cash_accept_event_handler(myCTMCashAccept);
should work.
Remember that the #define LIBCTMCLIENT_FUNC you showed is about the convention for user code calling the DLL; while the callback, with its typedef, is about the other way: it is the DLL calling the user code. They do not have to use the same conventions (although it is clearer when they do); so if your user code is likely to use __cdecl code (perhaps because it already exists), then you should remove the __stdcall from the typedef (and it should work, too).

Related

Why does the `of_find_compatible_node` function have two definitions in `/kernel/include/linux/of.h`, and how is the definition chosen?

The function of_find_compatible_node has two definition. One is
static online struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compatible)
another is
extern struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compatible)
These functions are defined the same.I know the keyword static online and extern,but I don't understand :
When I use the function,what does the compiler choose?
Why are two functions not redefined?
In base.c and include<of.h>, there appears to be a re-definition of struct_device_node *of_find_comatible_node(struct device_node *from,const char *type,const char *compatible). Why? I think it causes redefinition when linking.
This is a very common pattern in kernel headers (and not just there). If you take a closer look at the file (or use an editor that does code folding), you can notice that both lines are inside conditional compilation blocks, like this:
#ifdef CONFIG_OF
extern struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
#else /* CONFIG_OF */
static inline struct device_node *of_find_compatible_node(
struct device_node *from,
const char *type,
const char *compat)
{
return NULL;
}
#endif
Thus if CONFIG_OF is enabled, the former part gets compiled in and serves as a declaration of the function, whose real definition is placed in some .c file. If the kernel is configured without CONFIG_OF, the #else branch will be used, supplying a dummy no-op implementation of the function so that the rest of the kernel still compiles correctly.
The dummy implementation is also static inline, allowing the compiler to just replace calls to it by a constant NULL value and likely optimize whole code paths away, decreasing code size and eliminating runtime overhead.

How to open a thread in MFC to run a cuda function?

I now change my cuda program into an MFC project, I wrote the function of .cu as an interface function, So I can call it in MFC's dlg,Because I now use the UI thread call, I want to open a work thread to call, but failed.I am making AfxBeginThread, but it does not recognize my interface function.
I use vs2013, win7.
my interface function like this:
extern "C" float solveGPU(M_args Parameter_, double Mtime)
You could AfxBeginThread use but you have to call yout function from a new function or a static method with he following prototype:
UINT __cdecl MyControllingFunction( LPVOID pParam );
like this:
UINT __cdecl SolveGPUThreadFunction( LPVOID pParam )
{
YourDialogClass* pThis = (YourDialogClass*)(pParam);
pThis->result= solveGPU(pThis->Parameter_, pThis->Mtime);
}
and pass this pointer of your dialog as pParam of AfxBeginThread:
CWinThread* pCUDAThread = AfxBeginThread(&SolveGPUThreadFunction, this);
But you can think about using the std::thread instead.

error LNK2019: unresolved external symbol __imp__debugf referenced in function "int __cdecl fld_new

I am upgrading my project from VS 6 to VS 2010, while building in release mode, I am facing the below error.
1>Creating library .\Release\JfFrpF32.lib and object .\Release\JfFrpF32.exp>
1>FLD_.obj : error LNK2019: unresolved external symbol __imp__debugf referenced in function "int __cdecl fld_new(char *,unsigned char,unsigned char,short,char,char,unsigned char,short,char,double,double,short,char *,char,short,short)" (?fld_new##YAHPADEEFDDEFDNNF0DFF#Z)
1>Release/JfFrpF32.dll : fatal error LNK1120: 1 unresolved externals
1>
1>Build FAILED.
Please help me .. thanks in advance..
Common problems that cause LNK2019 include:
The declaration of the symbol contains a spelling mistake, such that,
it is not the same name as the definition of the symbol.
A function was used but the type or number of the parameters did not
match the function definition.
The calling convention (__cdecl, __stdcall, or __fastcall) differs on
the use of the function declaration and the function definition.
Symbol definitions are in a file that was compiled as a C program and
symbols are declared in a C++ file without an extern "C" modifier. In
that case, modify the declaration.
For More Information See Here
In my case, even though I used extern "C", I got the unresolved symbol error.
The hpp was
extern "C"
{
class A
{
public:
void hi();
};
A* a;
DECLDIR int Connect();
}//extern
and the cpp was
#include "DatabasePlugin.hpp"// Include our header, must come after #define DLL_EXPORT
extern "C" // Get rid of name mangling
{
DECLDIR int Connect()
{
a = new A();
a->hi();
return 0;
}//Connect
}//extern
The problem was that I had not created an implementation for the hi() function. Adding it solved the problem. Like this:
extern "C" // Get rid of name mangling
{
void A::hi() {}
DECLDIR int Connect()
{
a = new A();
a->hi();
return 0;
}//Connect
}//extern
Having to declare Hi() before Connect() may also be significant.

Is this interface binary compatible between MSVC and mingw?

I am working on a library that allows its users (other libraries residing in the same process) to exchange data buffers and streams. The library has to be usable from both MSVC and mingw code (more compatibility doesn't hurt, but is not strictly necessary). In order to achieve this, the core functionality should be provided from a small, compiler-compatible interface that can be hidden later by a convenience layer that is compiled with the client code.
A challenging aspect of the library is that it has to be extensible, so that clients can provide their own buffer and stream implementations, but the core library interface must remain stable once it is released. If you are interested in further background, you can read about it in the forum thread discussion.
I have tried to learn about problems of binary compatibility between compilers, but since I am new to this topic I would be interested in comments on my result. I am not interested in standards-defined behaviour here (the structs probably fail that test), only in compatibility between mingw and MSVC and maybe other compilers if conveniently possible.
In particular, will the structs be compatible? They uniformly consist of function pointers, so I don't think padding will be an issue. Additionally, is the stdcall convention necessary here, or would cdecl work just as well? Could I leave it unspecified then since both compilers will default to cdecl? Should I? Here is what I have right now:
#include <stdint.h>
typedef struct {
uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
void (__stdcall *write)(void*, const uint8_t*, uint32_t);
uint32_t (__stdcall *getBytesLeft)(void*);
uint8_t (__stdcall *destroy)(void*);
} SharedStreamInterface;
typedef struct {
uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
void (__stdcall *write)(void*, const uint8_t*, uint32_t);
uint32_t (__stdcall *getBytesLeft)(void*);
uint8_t (__stdcall *destroy)(void*);
uint32_t (__stdcall *getreadpos)(void*);
uint32_t (__stdcall *getwritepos)(void*);
uint32_t (__stdcall *getlength)(void*);
void (__stdcall *setreadpos)(void*, uint32_t);
void (__stdcall *setwritepos)(void*, uint32_t);
void (__stdcall *setlength)(void*, uint32_t);
} SharedBufferInterface;
extern "C" {
// Functions applicable for both buffers and streams
__stdcall uint32_t readData(uint32_t id, uint8_t* data, uint32_t size);
__stdcall void writeData(uint32_t id, const uint8_t* data, uint32_t size);
__stdcall uint32_t getBytesLeft(uint32_t id);
__stdcall void destroyStreamOrBuffer(uint32_t id);
__stdcall uint8_t streamOrBufferExists(uint32_t id);
// Functions only applicable for buffers
__stdcall uint32_t getReadPos(uint32_t id);
__stdcall uint32_t getWritePos(uint32_t id);
__stdcall uint32_t getLength(uint32_t id);
__stdcall void setReadPos(uint32_t id, uint32_t pos);
__stdcall void setWritePos(uint32_t id, uint32_t pos);
__stdcall void setLength(uint32_t id, uint32_t length);
__stdcall uint8_t bufferExists(uint32_t id);
// Adding new buffers/Streams
__stdcall uint32_t addStream(SharedStreamInterface *interface, void *stream);
__stdcall uint32_t addBuffer(SharedBufferInterface *interface, void *buffer);
}
Edit: The project this was meant for has been on hold for a while now and probably needs a lot of rethinking if it's ever unshelved again. I'm leaving the question up though, because I'm still interested in the answer.
Yes, they will be compatible. That's the beauty with structs. As long as you don't introduce padding issues (which indeed wouldn't be the case here as you correctly pointed out), or in C++ add functionality to the structs that will result in - compiler-specific - vtable layouts, this will be always compatible.
You will also notice that from the Windows headers the C declarations of COM interfaces use structs in much the same way you do.
Side-note: the SharedStreamInterface::destroy member begs the question whether there is also one to "create" such a stream. You may want to share that as well. But your mileage may vary ...
As for the question of the calling convention, both __cdecl and __stdcall should work across the binaries, however I would always prefer __stdcall for another reason: it is compatible with more "languages" (i.e. tools) than __cdecl.
For style: use a #define to declare the calling convention explicitly (as you do) similar to WINAPI from the Windows headers.

Linux: How to get full name of shared object just loaded from the constructor?

On Windows, several arguments are passed to the DllMain constructor:
BOOL WINAPI DllMain(
__in HINSTANCE hinstDLL,
__in DWORD fdwReason,
__in LPVOID lpvReserved
);
From hinstDLL I can get the fully qualified file name of the DLL itself using GetModuleFileName():
LPTSTR str = new TCHAR[256];
int libNameLength = GetModuleFileName(hinstDLL, str, 256);
delete[] str;
In the example above, str now contains the full name of the DLL just loaded, e.g., C:\Windows\System32\MyFile.dll.
On Linux, no arguments are passed to the shared object constructor:
void `__attribute__` ((constructor)) on_load(void);
How do I get the full name of the DLL in this case? Extra credit if your solution works on Mac, too. :-)
I think the dladdr function might do what you want. From the man page:
The function dladdr() takes a function pointer and tries to resolve
name and file where it is located. Information is stored in the
Dl_info structure:
typedef struct {
const char *dli_fname; /* Pathname of shared object that
contains address */
void *dli_fbase; /* Address at which shared object
is loaded */
const char *dli_sname; /* Name of nearest symbol with address
lower than addr */
void *dli_saddr; /* Exact address of symbol named
in dli_sname */
} Dl_info;
If no symbol matching addr could be found, then dli_sname and
dli_saddr are set to NULL.
dladdr() returns 0 on error, and non-zero on success.
So you just give it a function pointer (like the address of the constructor itself), and it will give you the filename and a bunch of other information. Here's some sample code:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
__attribute__((constructor))
void on_load(void) {
Dl_info dl_info;
dladdr(on_load, &dl_info);
fprintf(stderr, "module %s loaded\n", dl_info.dli_fname);
}
EDIT: It looks like this function exists on OS X, too, with the same semantics.
One supremely ugly and horrible way to do this is to look through /proc/pid/maps and look for the mapping that encompasses the address of the on_load function being executed.

Resources