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!
source to share
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
source to share
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.
source to share
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.
source to share