When writing a win32 api wrapper with C ++, how to pass this pointer to a static function
I want to convert a function object to a function.
I wrote this code but it doesn't work.
#include <iostream>
typedef int (*int_to_int)(int);
struct adder {
int n_;
adder (int n) : n_(n) {}
int operator() (int x) { return x + n_; }
operator int_to_int () {
return this->*&adder::operator();
}
};
int main(void) {
adder add_two(2);
int_to_int add_fn = add_two;
std::cout << add_two(3) << std::endl; // expect 5
std::cout << add_fn(3) << std::endl; // expect 5
add_fn = adder(5);
std::cout << add_fn(3) << std::endl; // expect 8
return 0;
}
and I got a message from g ++ says invalid use of non-static member function
.
How do I get a pointer to an instance member function?
Edit . My initial problem is with the Win32 API.
I am forced to write a Windows program with the old Win32 API at school. but I don't want to write a terrible switch statement like some code examples to text. Then I decided to write a wrapper in C ++.
I want to write a window class like ...
class Window {
public:
LRESULT update (HWND, UINT, WPARAM, LPARAM);
void run();
// below methods are called by update()
virtual void onclick(int, int);
virtual void ondraw(); // ... and more methods
};
and I am ready to write an application class with getting this class and overloading some methods.
Finally, my actual sampler is how to do this in C ++.
// on initializing my window object,
// I must register window class with callback which is
// not a C++ function object.
// I try to explain what I want to do with psudocode mixing C++ and javascript.
WNDCLASS wndclass;
Window *self = this;
wndclass.lpfnWndProc = function () {
return self.update.apply(self, argunemts);
};
In other words, I have to do a closure in the function pointer. I don't know how to do this, but I cannot believe that it is not possible to do this in C ++.
Edit . The original title of this question is "How to get an instance-pointer-instance". But that title and my question didn't talk about my actual problem. Sorry for the early responders and the bulb, thanks for the suggestion and very helpful answer!
Refresh . You told us what you want. I found this question here on SO: Best way to store this pointer for use in WndProc . I'm not a Windows programmer, but Adam Rosenfield's guy seems to be right using SetWindowLongPtr and GetWindowLongPtr. So, you use it like this:
LRESULT CALLBACK my_callback(HWND hwnd, UINT ui, WPARAM wp, LPARAM lp) {
Window * self = reinterpret_cast<Window*>(
GetWindowLongPtr(hwnd, 0));
return self->update(hwnd, ui, wp, lp); // handle it.
}
Register this function as wnd-proc and store a pointer to this
your Window object with SetWindowLongPtr. There WNDCLASSEX
is a field in the structure cbWndExtra
that you assign sizeof(Window*)
that has enough storage space to just hold this pointer. Then you can call
SetWindowLongPtr(my_hwnd, 0, reinterpret_cast<LONG_PTR>(this));
to place this pointer in this area. Then get it as above and pass in a valid member function. In theory, you can also use a static member function. But you have to be careful. Calling a static member function from C code can cause errors because the calling convention may differ from C code and C ++ code. For Windows, this might not be a problem - I don't know. So you better check yourself.
What you are trying to do is wrong. You are trying to return a pointer to a function call operator, but there is no object when the object is called, except that your conversion operator is of the wrong type. The type returned by a conversion operator is of the type of a function pointer, but not of the type of a member function pointer. The closest you can get is to use the correct type:
struct adder;
typedef int (adder::*int_to_int)(int);
struct adder {
int n_;
adder (int n) : n_(n) {}
int operator() (int x) { return x + n_; }
operator int_to_int () {
return &adder::operator();
}
};
Now your conversion operator is not even considered because it needs to be called like this:
adder a(10); cout << (a.*(int_to_int)a)(2); // expected: 12
And manually:
// note, we just get the member function pointer using the conversion operator.
// Nothing is related to the actual temporary adder object.
int_to_int i = adder(5);
cout << (adder(10).*i)(2); // expected: 12
Normal function call syntax does not handle this. In short, what you are trying is not possible.
I think one more question is: why do you want this? I think we can help you better when we know what the original problem is. If you're trying to make it look and work like a function call, you don't need any conversion operators:
struct adder {
int n_;
adder (int n) : n_(n) {}
int operator() (int x) { return x + n_; }
};
adder a(10); cout << a(2); // expected: 12
Instance method pointers are a bit tricky and are completely different animals compared to "normal" function pointers.
See what the C ++ FAQ lite section 33 has to say about it . Also see this and this one for specific examples.
A pointer to a non-static member function is different from a pointer to a static function (or to a global and therefore static function) because non-static members have a hidden "this" parameter.
A type for globals or statics is something like int (*) (int)
However, the type for nonstatic is something like int (ClassName :: *) (int).
That being said, your code has weirder things in it as you are trying to assign a constructor or constructed object to your function pointer.