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!

+1


source to share


3 answers


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

      

+4


source


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.

+1


source


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.

0


source







All Articles