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
Related
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
In my code I'm using Item 32 advice from Scott Meyers Effective Modern C++, where he explains how to move into the capture in C++11. The sample code works well.
class Some
{
public:
void foo()
{
std::string s = "String";
std::function<void()> lambda = std::bind([this](std::string& s) {
bar(std::move(s));
}, std::move(s));
call(std::move(lambda));
}
void bar(std::string)
{
// Some code
}
void call(std::function<void()> func)
{
func();
}
};
int main()
{
Some().foo();
}
Then I tried to use move in the capture in more difficult way with parameters, but it doesn't work, there are some compilation errors. Please, help me to fix it. Code with error below. I've played with it, but couldn't find a solution. Is it possible to do it?
class Some
{
public:
void foo()
{
std::string stringToMove = "String";
std::function<void(std::string, int, int)> lambda =
std::bind([this](std::string s, int i1, int i2, std::string& stringToMove) {
bar(std::move(stringToMove), i1, i2);
}, std::move(stringToMove));
call(std::move(lambda));
}
void bar(std::string, int, int)
{
// Some code
}
void call(std::function<void(std::string, int, int)> func)
{
func(std::string(), 5, 5);
}
};
int main()
{
Some().foo();
}
Errors:
Severity Code Description Project File Line Suppression State
Error C2672 'std::invoke': no matching overloaded function
found drafts c:\program files (x86)\microsoft visual studio
14.0\vc\include\type_traits 1468
Severity Code Description Project File Line Suppression State
Error C2893 Failed to specialize function template 'unknown-type
std::invoke(_Callable &&,_Types &&...)' drafts c:\program files
(x86)\microsoft visual studio 14.0\vc\include\type_traits 1468
std::bind requires of you to specify all the parameters. So those which should be passed to the resulting function object, need to be placeholders.
std::function<void(std::string, int, int)> lambda =
std::bind([this](std::string s, int i1, int i2, std::string& stringToMove) {
bar(std::move(stringToMove), i1, i2);
}, _1, _2, _3, std::move(stringToMove));
I m reading The C++ Programming Language 4e. In the part of Default Argument I dont understand below code. I try to compile but there is an error. Anyway what Bjarne trying to explaing? A default argument is type checked at the time of the function declaration and evaluated at the
time of the call. For example:
class X
{
public:
static int def_arg;
void f(int = def_arg);
// ...
};
int X::def_arg = 7;
void g(X& a)
{
a.f(); // maybe f(7)
a.def_arg = 9;
a.f(); // f(9)
}
Error is :
unresolved external symbol "public: void __thiscall X::f(int)" (?f#X##QAEXH#Z) referenced in function "void __cdecl g(class X &)" (?g##YAXAAVX###Z)
MS c++ 2013
You just declared f but need to define the body of f:
void f(int = def_arg);
For example
void X::f(int)
{
// Do something
}
or
class X
{
// ...
void f(int = def_arg)
{
// Do something
}
};
Live code.
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);
}
I think they are called functors? (it's been a while)
Basically, I want to store a pointer to a function in a variable, so I can specify what function I want to use from the command line.
all the functions return and take the same values.
unsigned int func_1 (unsigned int var1)
unsigned int func_2 (unsigned int var1)
function_pointer = either of the above?
so then I could call it by going: function_pointer(my_variable)?
EDIT:
as per #larsmans's suggestion, I've gotten this:
Config.h:
class Config
{
public:
unsigned static int (*current_hash_function)(unsigned int);
};
Config.cpp:
#include "Config.h"
#include "hashes.h"
unsigned static int (*current_hash_function)(unsigned int) = kennys_hash_16;
hashes.h:
unsigned int kennys_hash(unsigned int out);
unsigned int kennys_hash_16(unsigned int out);
hashes.cpp:
just implements the functions in the header
main.cpp:
#include "Config.h"
#include "hashes.h"
// in test_network:
unsigned int hashed = Config::current_hash_function(output_binary);
//in main():
else if (strcmp(argv[i], "-kennys_hash_16") == 0)
{
Config::current_hash_function = kennys_hash_16;
}
else if (strcmp(argv[i], "-kennys_hash_8") == 0)
{
Config::current_hash_function = kennys_hash;
}
the error I get:
g++ -o hPif src/main.o src/fann_utils.o src/hashes.o src/Config.o -lfann -L/usr/local/lib
Undefined symbols:
"Config::current_hash_function", referenced from:
test_network() in main.o // the place in the code I've selected to show
auto_test_network_with_random_data(unsigned int, unsigned int, unsigned int)in main.o
generate_data(unsigned int, unsigned int, unsigned int)in main.o
_main in main.o // the place in the code I've selected to show
_main in main.o // the place in the code I've selected to show
generate_train_file() in fann_utils.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [hPif] Error 1
The simplest you can do is
unsigned int (*pFunc)(unsigned int) = func_1;
This is a bare function pointer, which cannot be used to point to anything other than a free function.
You can make it less painful if your compiler supports the C++0x auto keyword:
auto pFunc = func_1;
In any case, you can call the function with
unsigned int result = pFunc(100);
There are many other options that provide generality, for example:
You can use boost::function with any C++ compiler
With a compiler implementing features of C++0x you can use std::function
These can be used to point to any entity that can be invoked with the appropriate signature (it's actually objects that implement an operator() that are called functors).
Update (to address updated question)
Your immediate problem is that you attempt to use Config::current_hash_function (which you declare just fine) but fail to define it.
This defines a global static pointer to a function, unrelated to anything in class Config:
unsigned static int (*current_hash_function)(unsigned int) = kennys_hash_16;
This is what you need instead:
unsigned int (*Config::current_hash_function)(unsigned int) = kennys_hash_16;
From C++11 you can use std::function to store functions. To store function you use it as follsonig:
std::function<return type(parameter type(s))>
as an example here it is:
#include <functional>
#include <iostream>
int fact (int a) {
return a > 1 ? fact (a - 1) * n : 1;
}
int pow (int b, int p) {
return p > 1 ? pow (b, p - 1) * b : b;
}
int main (void) {
std::function<int(int)> factorial = fact;
std::function<int(int, int)> power = pow;
// usage
factorial (5);
power (2, 5);
}
No, these are called function pointers.
unsigned int (*fp)(unsigned int) = func_1;
You could also use function either from the c++0x or from boost.
That would be
boost::function<int(int)>
and then use bind to bind your function to this type.
Have a look here and here
Ok here would be a example. I hope that helps.
int MyFunc1(int i)
{
std::cout << "MyFunc1: " << i << std::endl;
return i;
}
int MyFunc2(int i)
{
std::cout << "MyFunc2: " << i << std::endl;
return i;
}
int main(int /*argc*/, char** /*argv*/)
{
typedef boost::function<int(int)> Function_t;
Function_t myFunc1 = boost::bind(&MyFunc1, _1);
Function_t myFunc2 = boost::bind(&MyFunc2, _1);
myFunc1(5);
myFunc2(6);
}
You can store a function in a variable in c++ in this way
auto function_name = [&](params){
statements
};
auto add = [&](int a,int b){
return a+b;
};
cout<<add(5,6);
typedef unsigned int (*PGNSI)(unsigned int);
PGNSI variable1 = func_1;
PGNSI variable2 = func_2;
unsigned int (* myFuncPointer)(unsigned int) = &func_1;
However, the syntax for function pointers is awful, so it's common to typedef them:
typedef unsigned int (* myFuncPointerType)(unsigned int);
myFuncPointerType fp = &func_1;
IF you have Boost installed, you can also check out Boost Function.