QtConcurrent::run() doesn't accept __stdcall/WINAPI function - c++

I was trying to execute a DLL function that has __stdcall calling convention using QtConcurrent::run(), but I am getting compile errors.
I've reduced the problem to this example code:
__stdcall void dllFunc() {
qDebug() << "test";
}
void test() {
QtConcurrent::run(dllFunc);
}
If I remove __stdcall the code compiles and runs fine. Otherwise I get these compile errors:
error: invalid conversion from 'void (*)()' to 'void (*)()'
error: initializing argument 1 of 'QFuture<T> QtConcurrent::run(T (*)()) [with T = void]'
Why is this happening, and what is the best workaround?

Well, for a workaround, I ended up using a wrapper function with the same signature but no __stdcall convention:
__stdcall int dllFunc(int param1, void *param2) {
qDebug() << "test";
return 0;
}
int dllFuncWrapper(int param1, void *param2) {
return dllFunc(param1, param2);
}
void test() {
QtConcurrent::run(dllFuncWrapper);
}

Related

Windows C++ Wrap dll into class Error: incompatible with parameter and non-standard syntax

I have a working example in single file with its spapidllm64.h but wanna split into separate files for easier coding. I have tried to reduce it into a minimal version as follows:
// spapidll.h
#define SPDLLCALL __stdcall
typedef void (SPDLLCALL *LoginReplyAddr)(char *user_id, long ret_code, char *ret_msg);
typedef void (SPDLLCALL *p_SPAPI_RegisterLoginReply)(LoginReplyAddr addr);
typedef int (SPDLLCALL *p_SPAPI_Login)();
//main.cpp
void SPDLLCALL LoginReply(char *user_id, long ret_code, char *ret_msg);
p_SPAPI_RegisterLoginReply SPAPI_RegisterLoginReply;
p_SPAPI_Login SPAPI_Login;
int main(void)
{
HINSTANCE hInst = LoadLibrary("spapidllm64.dll");
SPAPI_RegisterLoginReply = (p_SPAPI_RegisterLoginReply)GetProcAddress(hInst, "SPAPI_RegisterLoginReply");
SPAPI_RegisterLoginReply(LoginReply);
SPAPI_Login = (p_SPAPI_Login)GetProcAddress(hInst, "SPAPI_Login");
int rc = SPAPI_Login();
printf("\nSPAPI_Login: %d\n", rc);
Sleep(3000);
FreeLibrary(hInst);
return 0;
}
void SPDLLCALL LoginReply(char *user_id, long ret_code, char *ret_msg)
{
printf("\nLoginReply[%s]: Ret code: %d, Ret msg: %s",user_id, ret_code, (ret_code == 0)?"OK":ret_msg);
}
now I want to put those codes into a class like this:
// test.h
class ApiTester
{
public:
HINSTANCE hInst;
ApiTester(void){
hInst = LoadLibrary("spapidllm64.dll");
}
~ApiTester(void){
FreeLibrary(hInst);
}
void RegisterDLL();
int Login();
void SPDLLCALL LoginReply(char *user_id, long ret_code, char *ret_msg);
void SPDLLCALL ConnectingReply(long host_type, long con_status);
p_SPAPI_RegisterLoginReply SPAPI_RegisterLoginReply;
p_SPAPI_RegisterConnectingReply SPAPI_RegisterConnectingReply;
p_SPAPI_Login SPAPI_Login;
};
// test.c
#include "tester.h"
void ApiTester::RegisterDLL()
{
SPAPI_RegisterLoginReply = (p_SPAPI_RegisterLoginReply)GetProcAddress(hInst, "SPAPI_RegisterLoginReply");
SPAPI_RegisterLoginReply(LoginReply); // Error E0167 C3867
SPAPI_Login = (p_SPAPI_Login)GetProcAddress(hInst, "SPAPI_Login");
}
int ApiTester::Login()
{
int rc = SPAPI_Login();
printf("\nSPAPI_Login: %d\n", rc);
}
void SPDLLCALL ApiTester::LoginReply(char *user_id, long ret_code, char *ret_msg){
printf("\nLoginReply[%s]: Ret code: %d, Ret msg: %s",user_id, ret_code, (ret_code == 0)?"OK":ret_msg);
}
Then Windows VS C++ shows this error:
Error (active) E0167 argument of type "void (__stdcall ApiTester::*)(char *user_id, long ret_code, char *ret_msg)" is incompatible with parameter of type "LoginReplyAddr"
Error C3867 'ApiTester::LoginReply': non-standard syntax; use '&' to create a pointer to member
Not sure why it works in single file but couldn't work in this way. I thought it should be straight-forward(Hopefully, there is no typo). I'd be appreciate if there is any help.
typedef void (SPDLLCALL *LoginReplyAddr)(char *user_id, long ret_code, char *ret_msg);
typedef void (SPDLLCALL *p_SPAPI_RegisterLoginReply)(LoginReplyAddr addr);
According to the definition above, LoginReplyAddr is a function pointer, not a class member function pointer.
void ApiTester::RegisterDLL()
{
SPAPI_RegisterLoginReply = (p_SPAPI_RegisterLoginReply)GetProcAddress(hInst, "SPAPI_RegisterLoginReply");
SPAPI_RegisterLoginReply(LoginReply); // Error E0167 C3867
...
In this code, LoginReply is class member function pointer.
void (__stdcall ApiTester::*)(char *user_id ...
I guess that is the problem.
If you want to use the class member function as a callback, you also have to pass the 'this' of the class.
Or you can use the static member function.
The link below could help you.
Using a C++ class member function as a C callback function

Convert void (*)() to void (*)(unsigned char)

I'm trying to convert a void (*)() to void (*)(unsigned char) but my knowledge in C++ isn't good enough. I searched, but I could not find any examples. So I thought to create a function of function but I get some error:
typedef void (* voidFuncPtr)();
void castHandler(voidFuncPtr handler)(uint8_t gpio_num)
{
handler();
}
void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode)
{
// typedef void (* voidFuncPtr)();
// typedef void (* gpio_interrupt_handler_t)(uint8_t gpio_num);
// typedef void (* gpio_interrupt_handler_t)(unsigned char)
gpio_set_interrupt(pin, GPIO_INTTYPE_EDGE_ANY, castHandler(handler));
}
error: 'castHandler' declared as function returning a function void
castHandler(voidFuncPtr handler)(uint8_t gpio_num)
error: 'castHandler' was not declared in this scope
gpio_set_interrupt(pin, GPIO_INTTYPE_EDGE_ANY, castHandler(handler));
Can someone help me?
You need to maintain a table of handlers for each GPIO. Something like the following (untested and incomplete - some initializations and error checking are omitted) code:
typedef void (* voidFuncPtr)();
voidFuncPtr handlers[MAX_HANDLERS];
void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode)
{
handlers[pin] = handler;
}
void handleGPIO(unsigned char pin)
{
if (handlers[pin])
handlers[pin]();
}
void enableGPIOInterrupts(void)
{
/// Do this for each available pin
gpio_set_interrupt(pin, GPIO_INTTYPE_EDGE_ANY, handleGPIO);
}
Why not just write a function to do a redirection i.e.
void redirectFunction(unsigned char)
{
handler();
}
then
gpio_set_interrupt(pin, GPIO_INTTYPE_EDGE_ANY,redirectFunction);
EDIT
Perhaps this in C++:
void redirectFunction(std::function<void()> handler, unsigned char)
{
handler();
}
void wibble() { }
gpio_set_interrupt(pin, GPIO_INTTYPE_EDGE_ANY,
std::bind(redirectFunction, _1, wibble)
);

Visual C++ function and bind problems

I have a class which works with files, the constructor is receiving a std::function for sending the status of the work to a GUI Library if used.
Declaration:
DASM(std::string filename, std::function<void(unsigned int, unsigned int)> f = nullptr);
in the definition I have wrote:
if(f!=nullptr)
f(i,decodedInstructionsCount);
my LoadWindow has following function:
std::function<void(unsigned int,unsigned int)> get_f()
{
std::function<void(unsigned int,unsigned int)> ret = std::bind(&LoadWindow::pb_next,_2,_1);
return ret;
}
and the void LoadWindow::pb_next looks like this:
void LoadWindow::pb_next(unsigned int now, unsigned int max)
{
this->m_progressbar.set_fraction(((double)now/(double)max));
}
VC++ says:
error C2064: Expression does not resolve in a function which accepts 2 arguements.
I have a German VS so I translated the error.
Thank you for Help

Compile error with C++11 std::bind and auto for Callback function parameter

Hi I am having an issue compiling the following code. I am using auto and std::bind to bind a callback function with arguments. However, after passing this callback function as a parameter, it has issues compiling. Do you see an issue with the function declarations below:
#include <iostream>
#include <functional>
using namespace std;
class VmapPlayer
{
public:
void startPlayback();
void playAdBreak(int adBreak, void (VmapPlayer::*callback)());
void playSingleAd(int ad, void (VmapPlayer::*callback)(int adBreak, void (VmapPlayer::*cb)()));
};
void VmapPlayer::playSingleAd(int ad, void (VmapPlayer::*callback)(int adBreak, void (VmapPlayer::*cb)()))
{
cout << "i am here" << endl;
// OPTION #1 I would like to call this function
//(this->*callback)(adBreak, cb);
// OPTION #2 I would like this call this function without the params:
//(this->*callback)();
}
void VmapPlayer::playAdBreak(int adBreak, void (VmapPlayer::*callback)())
{
auto cb = std::bind(&VmapPlayer::playAdBreak, adBreak, callback);
playSingleAd(123, cb);
}
void VmapPlayer::startPlayback()
{
playAdBreak(456, &VmapPlayer::startPlayback);
}
int main()
{
VmapPlayer p;
p.startPlayback();
return 0;
}
Please see below for the compile error log:
main.cpp||In member function 'void VmapPlayer::playAdBreak(int, void (VmapPlayer::*)())':|
main.cpp|28|error: no matching function for call to 'VmapPlayer::playSingleAd(int, std::_Bind<std::_Mem_fn<void (VmapPlayer::*)(int, void (VmapPlayer::*)())>(int, void (VmapPlayer::*)())>&)'|
main.cpp|28|note: candidate is:|
main.cpp|14|note: void VmapPlayer::playSingleAd(int, void (VmapPlayer::*)(int, void (VmapPlayer::*)()))|
main.cpp|14|note: no known conversion for argument 2 from 'std::_Bind<std::_Mem_fn<void (VmapPlayer::*)(int, void (VmapPlayer::*)())>(int, void (VmapPlayer::*)())>' to 'void (VmapPlayer::*)(int, void (VmapPlayer::*)())'|
||=== Build finished: 1 errors, 0 warnings (0 minutes, 0 seconds) ===|
I supposed my question can be simplified as:
What does the function declaration for playSingleAd() need to be in order to compile the following successfully?:
void VmapPlayer::playAdBreak(int adBreak, void (VmapPlayer::*callback)())
{
auto cb = std::bind(&VmapPlayer::playAdBreak, adBreak, callback);
playSingleAd(123, cb);
}
When you bind a method to fully-supplied parameters, the resulting functor takes no arguments. In your code, playSingleAd takes a function pointer that takes as an argument, a function pointer whose arguments are to be supplied when called. Because you already bound the arguments to that function pointer, the arguments thereto cannot not be specified in the function signature.
Anyway, your code can be improved with the use of std::function. Moreover, the function will have to take the instance as an argument, as shown in the implementation of playSingleAd below:
class VmapPlayer
{
public:
void startPlayback();
void playAdBreak(int adBreak, void (VmapPlayer::*callback)());
void playSingleAd(int ad, std::function<void (VmapPlayer&)>);
};
void VmapPlayer::playSingleAd(int, std::function<void (VmapPlayer&)> callback)
{
cout << "i am here" << endl;
callback(*this);
}
void VmapPlayer::playAdBreak(int adBreak, void (VmapPlayer::*callback)())
{
using namespace std::placeholders;
auto cb = std::bind(&VmapPlayer::playAdBreak, _1, adBreak, callback);
playSingleAd(123, cb);
}

How do I declare a C++ prototype with a void * pointer so that it can take any pointer type?

I want to create a function prototype in C++ so that there is a void * argument that can take pointers of any type. I know that this is possible in C. Is it possible in C++?
[EDIT] Here is a simplified version of the code that I am trying to get to work:
#include <stdio.h>
void func(void (f)(const void *))
{
int i = 3;
(*f)(&i);
}
void func_i(const int *i)
{
printf("i=%p\n",i);
}
void func_f(const float *f)
{
printf("f=%p\n",f);
}
void bar()
{
func(func_i);
}
And here is the compiler output:
$ g++ -c -Wall x.cpp
x.cpp: In function ‘void bar()’:
x.cpp:21: error: invalid conversion from ‘void (*)(const int*)’ to ‘void (*)(const void*)’
x.cpp:21: error: initializing argument 1 of ‘void func(void (*)(const void*))’
$ %
You may use void*, just as with C, but you'll need to cast your argument when calling it. I suggest you use a template function
template<typename T>
void doSomething(T* t) {...}
Yes.
int i = 345;
void * ptr = &i;
int k = *static_cast&lt int* &gt(ptr);
UPDATE ::
What you have shown in the code certainly cannot be done in C++.
Casting between void and any other must always be explicitly done.
Check these SO link for more details on what the C -standard has to say:
1) http://stackoverflow.com/questions/188839/function-pointer-cast-to-different-signature
2) http://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type
How about:
void func(void *);
exactly like in C? : P