Passing Function Pointer of an interface function - c++

I have following situation, there are two interfaces:
interface ILLShapeAttribute
{
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
};
interface ILLShapeNotification
{
virtual bool IsUsed(const RECT& rcBounds) = 0;
virtual void DefineAttribute(const char* pszAttributeName, VARIANT* pvAttributeData) = 0;
}
And 2 functions:
INT LlShapeGetAttributeList(LPCWSTR pwszShapefileName, ILLShapeAttribute* pIAttrInfo);
INT LlShapeEnumShapes(LPCWSTR pwszShapefileName, ILLShapeNotification* pIInfo);
In those both functions I want to call the same function IterateRecords2 which should get the pointer to the function DefineAttribute, e.g. ILLShapeAttribute::DefineAttribute and ILLShapeNotification::DefineAttribute
I defined it this way:
void IterateRecords2(ifstream& file, void (*pDefineAttribute)(const char*, VARIANT*))
{
pDefineAttribute(NULL, NULL); //will be called with real values
}
Until now the code compiles and everythig is fine. But then I try to call the IterateRecords2 like
IterateRecords2(file, pIAttrInfo->DefineAttribute);
or
IterateRecords2(file, pIInfo->DefineAttribute);
I get the compiler error:
error C3867: 'ILLShapeAttribute::DefineAttribute': function call missing argument list; use '&ILLShapeAttribute::DefineAttribute' to create a pointer to member
Please: I know, that ILLShapeNotification could inherit from ILLShapeAttribute and then pass *ILLShapeAttribute instead of function pointer but I want to understand how it works.
Question: how can I pass the pointer to DefineAttribute to IterateRecords2?

Question: how can I pass the pointer to DefineAttribute to IterateRecords2?
You can't.
A pointer-to-member-function is not compatible with a pointer to function, and even if it was, you'd need an object to call it on, you can't just call a member function without an object.
Some options are:
1) Take a pointer-to-member-function and pass an object.
This would solve your compiler error, but to be able to pass different types of object that are not related by inheritance you would need IterateRecords2 to be a template:
template<typename T>
void IterateRecords2(ifstream& file, T* obj, void (T::*pDefineAttribute)(const char*, VARIANT*))
{
obj->pDefineAttribute(NULL, NULL);
}
Now you can use it like this:
IterateRecords2(file, pIAttrInfo, &ILLShapeAttribute::DefineAttribute);
or:
IterateRecords2(file, pIInfo, &ILLShapeNotification::DefineAttribute);
2) Bind an object and its member function into a callable type, and pass that:
void IterateRecords2(ifstream& file, std::function<void(const char*, VARIANT*)> DefineAttribute)
{
DefineAttribute(NULL, NULL);
}
Then call it like:
IterateRecords2(file, std::bind(&ILLShapeAttribute::DefineAttribute, pIAttrInfo));
If you can't use std::function and std::bind you can replace them with boost::function and boost::bind

Related

How can i pass a function as a function parameter in another function?

I am trying to use an Arduino library and to use one of it's functions as a parameter in my own function, but I don't know how can I do that.
I tried the code below but I get an error.
Any help will be appreciated.
P.S: I do not have an option to use auto keyword.
using namespace httpsserver;
HTTPServer Http;
typedef void (*Register)(HTTPNode*); // My typedef
Register Node = Http.registerNode;
When I am trying to call Node (...), I get the error below.
Cannot convert 'httpsserver::ResourceResolver::registerNode'
from type 'void (httpsserver::ResourceResolver::)(httpsserver::HTTPNode*)'
to type 'Register {aka void (*)(httpsserver::HTTPNode*)}'
How can I create a function pointer for the type :
'void (httpsserver::ResourceResolver::)(httpsserver::HTTPNode*)'
I want to use it as a parameter in another function:
// My Declaration
void Get(void(*Register)(httpsserver::HTTPNode*), const std::string& path);
// Usage
Get (Http.registerNode(...), ""); // Like so
How can I do that?
A member function pointer is not a function pointer.
typedef void (httpsserver::*Register)(HTTPNode*); // My typedef
Register Node = &httpsserver::registerNode;
usage:
void Get(void(httpsserver::*Register)(httpsserver::HTTPNode*), const std::string& path);
Get (&httpsserver::registerNode, "");
you have to pass the httpsserver::HTTPNode* into Register within Get.
If you want to bind the arguments to the function object and call it later, you want std::function<void()>:
void Get(std::function<void()>, const std::string& path);
Get ([&]{ Http.registerNode(...); }, "");
note, however, that this makes lifetime of the objects refered to within the {} above quite dangerous.

Compiler error wrapping an interpretable function

I have a legacy C code base, which I am migrating to C++ in a piecemeal fashion. It includes an interpreter, so there is a need to wrap static functions and arguments for use by the interpreter. So a typical function for export to the interpreter may have the following signature:
static void do_strstr(struct value * p)
and be exposed to the interpreter like so:
using vptr = void (*) ();
template <typename Func>
constexpr vptr to_vptr(Func && func)
{ return reinterpret_cast<vptr>(func); }
struct function string_funs[] = {
...
{ C_FN3, X_A3, "SSI", to_vptr(do_strstr), "find" },
...
};
This has been proven to work. The drawback with the method so far is that the called function must allocate memory onto a temporary stack. An improvement would be where the called function just returns a string, for example. This function is then wrapped, where the wrapper does the memory magic behind the scenes. This allows functions to created in a more vanilla way.
Here is an implementation which concatenates two strings using my improved method:
static std::string do_concata(struct value* p)
{
std::string s1 = (p)->gString();
std::string s2 = (p+1)->gString();
return s1+s2;
}
I create a helper function:
static void do_concata_1(struct value* p)
{
wrapfunc(do_concata)(p);
}
where the somewhat generic wrapper is defined as:
std::function<void(struct value*)>
wrapfunc(std::function<std::string(struct value*)> func)
{
auto fn = [=](struct value* p) {
std::string s = func(p);
char* ret = alloc_tmp_mem(s.size()+1);
strcpy(ret, s.c_str());
p->sString(ret);
return;
};
return fn;
}
which is exposed to the interpreter as follows:
struct function string_funs[] = {
...
{ C_FN2, X_A2, "SS", to_vptr(do_concata_1), "concata" },
...
};
I am not satisfied with this solution, though, as it requires a helper function for each function I define. It would be better if I could eliminate do_concata_1 and write another function that wraps the wrapfunc.
And this is where the problem is. If I write:
vptr to_vptr_1(std::function<void(struct value*)> func)
{
return to_vptr(wrapfunc(func));
}
then the compiler complains:
stringo.cc: In function ‘void (* to_vptr_1(std::function<void(value*)>))()’:
stringo.cc:373:30: error: could not convert ‘func’ from ‘std::function<void(value*)>’ to ‘std::function<std::__cxx11::basic_string<char>(value*)>’
return to_vptr(wrapfunc(func));
which is bizarre in my mind, because where did the std::__cxx11::basic_string<char> come from? It should be void, surely?
I'm at a loss to see what the fix should be. I am also a bit confused as to whether I should be passing copies of functions, references to functions, or the enigmatic && r-vale references.
In to_vptr_1(), func is established as a function that returns void. But func is passed to wrapfunc(), which expects a function that returns std::string. The compiler does not have a way to convert func from std::function<void(struct value*)> to std::function<std::string(struct value*)>, so it emits the error message.
reinterpret_cast from std::function to raw function pointer is not going to work. This question has some good discussion on the topic, and this one has a solution that could perhaps be reworked for this situation.

C++ Store Function without Argument

Say that you define a callback function as such:
typedef std::function<void(float)> Callback;
And you have a function as such:
void ImAFunction(float a)
{
//Do something with a
}
Is there a way to be able to store a function without an argument then pass one to it at a later time?
Such as this:
//Define the Callback storage
Callback storage;
storage = std::bind(ImAFunction, this);
//Do some things
storage(5);
This wont work which I explain with some of my real code below.
I can get close to what I wan't if I bind the value in with the std::bind function. Such as:
//Change
//storage = std::bind(ImAFunction, this);
storage = std::bind(ImAFunction, this, 5.0); //5.0 is a float passed
This works but when I go to pass a value through the function the outcome is whatever I set it to before:
storage(100); //Output is still 5
I am basing the fact that I think this is possible on this article.
http://www.cprogramming.com/tutorial/function-pointers.html
It doesn't use the function or bind functions but it does pass pointer arguments and performs exactly what I need. The reason I don't just skip the bind function is because I am trying to store the function in a class (private) and I can't store it if it's a template because it's created with the class.
The error produced above comes from this code:
struct BindInfo {
Callback keyCallback;
int bindType;
bool isDown;
bool held;
std::string name;
};
template <class T1>
void bindEvent(int bindType, T1* keydownObj, void(T1::*keydownF)(float), std::string name)
{
BindInfo newKeyInfo = { std::bind(keydownF, keydownObj), bindType, false, false, name };
inputBindings.insert(std::pair<int, BindInfo>(BIND_NULL, newKeyInfo));
};
The error is:
No viable conversion from '__bind<void(Main::*&)(float), Main *&>' to 'Callback' (aka 'function<void (float)>'
Is this possible? Thanks in advance.
You can include a placeholder for an unbound argument:
std::bind(&Main::ImAFunction, this, std::placeholders::_1);
If you find that a bit of a mouthful, a lambda might be more readable:
[this](float a){ImAFunction(a);}
It sounds like what you're looking for is a function pointer. While I don't have a lot of experience using them in C++ I have used them in C so: Yes, it is possible. Perhaps something like this:
void (*IAmAFunctionPointer)(float) = &IAmAFunction;
The best way to think about that line is, that IAmAFunctionPointer is a pointer (hence the *), it returns a void, and takes a float. Then later:
float a = 5;
IAmAFunctionPointer(a);
You could even design it so that the callback function is passed into the method (I assume this is what you're looking for).
void DoStuffThenCallback(float a, void (*callback)(float))
{
//DoStuff
callback(a);
}
further reading: http://www.cprogramming.com/tutorial/function-pointers.html

Function Pointer from base class

i need a Function Pointer from a base class. Here is the code:
class CActionObjectBase
{
...
void AddResultStateErrorMessage( const char* pcMessage , ULONG iResultStateCode);
...
}
CActionObjectCalibration( ): CActionObjectBase()
{
...
m_Calibration = new CCalibration(&CActionObjectBase::AddResultStateErrorMessage);
}
class CCalibration
{
...
CCalibration(void (CActionObjectBase::* AddErrorMessage)(const char*, ULONG ));
...
void (CActionObjectBase::* m_AddErrorMessage)(const char*, ULONG );
}
Inside CCalibration in a Function occurs the Error. I try to call the Function Pointer like this:
if(m_AddErrorMessage)
{
...
m_AddErrorMessage("bla bla", RSC_FILE_ERROR);
}
The Problem is, that I cannot compile. The Error Message says something like:
error C2064: Expression is no Function, that takes two Arguments.
What is wrong?
regards
camelord
You need to provide an object on which you call the member function:
CActionObjectBase* pActionObjectBase /* = get pointer from somewhere */ ;
(pActionObjectBase->*m_AddErrorMessage)("bla bla", RSC_FILE_ERROR);
Unlike normal object and function pointers, pointers to members can only be deferenced using an object of the appropriate type via the .* (for objects and references) or ->* (for pointers to objects) operators.
You need to invoke m_AddErrorMessage on an object, something like:
(something->*m_AddErrorMessage)(...)

I am new to threads, What does this compile error mean?

Using C++.
pthread_t threads[STORAGE]; // 0-99
...
void run()
Error>>> int status = pthread_create(&threads[0], NULL, updateMessages, (void *) NULL);
if (status != 0)
{
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
...
void ClientHandler::updateMessages(void *)
{
string reqUpdate = "91"; // Request for update
string recvMSG;
while (true)
{
sleep(5);
sending(sock,reqUpdate); // send
recvMSG = receiving(sock); // receive
QString output(recvMSG);
emit signal_chat(output, 0); // Print message to text box
}
}
...
Compile Error:
TCPClient.cpp:109: error: argument of type ‘void (ClientHandler::)(void*)’ does not match ‘void* (*)(void*)’
I can't figure out whats wrong.
Thanks in advance.
A pointer to a member function is different from a global function with the same signature since the member function needs an additional object on which it operates. Therefore pointers to these two types of functions are not compatible.
In this case this means that you cannot pass a member function pointer to pthread_create but only a pointer to a non-member (or static) function. A work around for this problem is to use the forth parameter of pthread_create to pass a pointer to a object to a global function which then calls the method of the passed object:
class ClientHandler {
public:
void updateMessages();
void run();
};
// Global function that will be the threads main function.
// It expects a pointer to a ClientHandler object.
extern "C"
void *CH_updateMessages(void *ch) {
// Call "real" main function
reinterpret_cast<ClientHandler*>(ch)->updateMessages();
return 0;
}
void ClientHandler::run() {
// Start thread and pass pointer to the current object
int status = pthread_create(&threads[0], NULL, CH_updateMessages, (void*)this);
...
}
It's nothing to do with threads, it's a normal C++ error, you're just passing an incompatible type of function pointer.
A function pointer is not the same as a member instance function pointer, even if their signature is the same; this is because there is an implicit reference to *this passed. You can't avoid this.
As pthread_create takes a free function, create a static function(is a free function) inside ClientHandler
static void Callback(void * this_pointer,int other_arg) {
ClientHandler* self = static_cast< ClientHandler*>(this_pointer);
self-> updateMessages(other_arg);
}
and call pthread_create as follows
pthread_create(&threads[0], NULL, &ClientHandler::Callback, (void *) pointer_to_ClientHandler,int other_arg);
That works because Callback is free function
YoLinux has a nice pthread tutorial that my help you in learning about threads.
As others have already said, the problem is that the signatures between the functions are different. Class member functions always have a "secret" extra parameter, the this pointer. So you can never pass a member function where a global function is expected. You can hack around this either with libraries such as Boost.Bind, or by making the function a static member of the class.
But the simplest, and most elegant solution is to use a different threading API.
Boost.Thread is a very nice threading library for C++ (pthreads is designed for C, and that's why it doesnt play well with C++ features such as class methods).
I'd recommend using that.
Your code could be rewritten as something like this:
class ClientHandler {
public:
ClientHandler(/* All the parameters you want to pass to the thread. Unlike pthreads you have complete type safety and can pass as many parameters to this constructor as you like */){...}
void operator()() // boost.thread calls operator() to run the thread, with no parameters. (Since all parameters were passed in the constructor and saved as member variables
{
string reqUpdate = "91"; // Request for update
string recvMSG;
while (true)
{
sleep(5);
sending(sock,reqUpdate); // send
recvMSG = receiving(sock); // receive
QString output(recvMSG);
emit signal_chat(output, 0); // Print message to text box
}
}
// whatever arguments you want to pass to the thread can be stored here as member variables
};
boost::threead_group gr; // can store all your threads here, rather than being limited to your fixed-size array
gr.create_thread(ClientHandler(/* construct a ClientHandler object with the parameters you like*/));
You're passing a member function instead of a global, normal, one.
Just define:
void updateMessages(void *) {
static ClientHandler c;
// use c..
}