Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: Supports class methods? #40

Open
brjoha opened this issue Jun 2, 2019 · 6 comments
Open

Question: Supports class methods? #40

brjoha opened this issue Jun 2, 2019 · 6 comments

Comments

@brjoha
Copy link

brjoha commented Jun 2, 2019

The README example illustrated hooks for global functions. Do hooks work for instanced class methods (virtual and non-virtual), and method overloads?

@Zeex
Copy link
Owner

Zeex commented Jun 2, 2019

It would probably work if you somehow obtain a pointer to the member function that you wish to hook and declare your function with __thiscall or something similar, but I haven't tried that to be honest.

@badbyte7
Copy link

Short: Yes.

Long: I had to recast the member function pointer, because my gcc refuses converting it directly to a void * (I casted it to a normal function pointer first).

It gets a little bit tricky if the function is a virtual one, because than the member function pointer is an index of the function in the vtable (at least in my gcc version). So you have to get the correct function pointer out of the vtable.

You also have some work to do, if the function is private, and you want to set the hook from outside. (Google for "C++ how to access of private members")

If you have everything up and running, you get the this pointer as first function argument. Of course you can only use the public members/methods, because you are outside in your C-function.

@SvarunSoda
Copy link

SvarunSoda commented Apr 7, 2024

Short: Yes.

Long: I had to recast the member function pointer, because my gcc refuses converting it directly to a void * (I casted it to a normal function pointer first).

Hey there,

Can you go into more detail on how you typecasted a class function to a void* poiner? That is usually considered an invalid conversion or UB, vast majority of compilers straight-up error it out, so I'm curious if there's a "correct" way of accomplishing it.

@attilabody
Copy link

#include <stdint.h>
#include <iostream>

using namespace std;

class C
{
public:
    void foo(int bar)
    {
        cout << reinterpret_cast<uintptr_t>(this) << " -> " << bar << endl;
    }
};

typedef void (C::*cvifptr_t)(int);
typedef void (*vifptr_t)(int, int);

int main(int argc, char **argv)
{
    C c;
    cvifptr_t zup = &C::foo;
    cout << zup << endl;
    vifptr_t baz = reinterpret_cast<vifptr_t>(zup);
    cout << baz << endl;
    (c.*zup)(123);
    (*baz)(1234, 321);
    return 0;
}

@SvarunSoda
Copy link

SvarunSoda commented Apr 8, 2024

#include <stdint.h>
#include <iostream>

using namespace std;

class C
{
public:
    void foo(int bar)
    {
        cout << reinterpret_cast<uintptr_t>(this) << " -> " << bar << endl;
    }
};

typedef void (C::*cvifptr_t)(int);
typedef void (*vifptr_t)(int, int);

int main(int argc, char **argv)
{
    C c;
    cvifptr_t zup = &C::foo;
    cout << zup << endl;
    vifptr_t baz = reinterpret_cast<vifptr_t>(zup);
    cout << baz << endl;
    (c.*zup)(123);
    (*baz)(1234, 321);
    return 0;
}

Thanks for your reply; however the line vifptr_t baz = reinterpret_cast<vifptr_t>(zup); fails to compile with both VS and cl.exe with error C2440: 'reinterpret_cast': cannot convert from 'cvifptr_t' to 'vifptr_t' note: There is no context in which this conversion is possible.

I see that you're converting the class function pointer zup to a standalone function pointer baz, and the calling it with 2 arguments. Is this supposed to represent the behaviour of the __thiscall convention, where the first argument is the this pointer to the class?

@attilabody
Copy link

attilabody commented Apr 9, 2024

Thanks for your reply; however the line vifptr_t baz = reinterpret_cast<vifptr_t>(zup); fails to compile with both VS and cl.exe with error C2440: 'reinterpret_cast': cannot convert from 'cvifptr_t' to 'vifptr_t' note: There is no context in which this conversion is possible.

I'm sorry to hear that, it compiles with a warning (which can be suppressed with -Wno-pmf-conversions) using GCC 13.2 on Linux (I recommend experimenting with different compilers on godbolt.org)

I see that you're converting the class function pointer zup to a standalone function pointer baz, and the calling it with 2 arguments. Is this supposed to represent the behaviour of the __thiscall convention, where the first argument is the this pointer to the class?

Exactly.

https://godbolt.org/z/qMqTWGn14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants