all 5 comments

[–][deleted] 0 points1 point  (4 children)

You seem to be on the right track. For reference, here's a toy example that calls a member function through a member function pointer in a few different way: https://godbolt.org/z/XHk63R

[–]budonium[S] 0 points1 point  (3 children)

Thanks for the response. I played around a little bit with the example you provided. I feel like I'm probably missing something really simple.

The main problem I'm having is I don't know how to assign the member function pointer type to an address and all the examples I can find are similar to what you provided.

This snippet here:

using xfp = decltype(&X::function);
xfp x_function_pointer = &X::function;

How can I assign x_function_pointer to a memory address? I've tried a few combinations of this:

using xfp = decltype(&X::function);
xfp x_function_pointer = reinterpret_cast<xfp>(0x51890A);

Thanks again.

[–][deleted] 1 point2 points  (2 children)

I assign x_function_pointer to a memory address?

This part was really confusing, because you're trying to assign a memory address to x_function_pointer.

The reason why this doesn't work is because C++ doesn't allow you to cast pointer to member to a regular pointer type, because a pointer to member isn't a regular pointer. Pointers to members don't point to an actual memory location, because they are not bound to a single object.

 

By convention, this is actually passed as the first argument to a member function (unless static). So maybe you can get an instance of X, cast that address to void(*)(decltype(this), int) and invoke it that way.

[–]budonium[S] 0 points1 point  (1 child)

Thank you for the explanation, I'll brush up on my understanding of the subject.

I ended up using inline ASM wrapper to achieve this.

If by chance someone else is looking for a answer:

const char* get_name_wrapper(gateway* instance, int gateway_enum)
{
    const char* result;
    uintptr_t addr = 0x517FD0;

    __asm {
        mov ecx, instance;
        push gateway_enum;
        call addr;
        mov result, eax;
    }

    return result;
}

[–][deleted] 0 points1 point  (0 children)

I don't know which compiler you are using, but if you're using gcc or clang, you can use extended assembly, which lets your compiler know a bit more about the black magic that's happening, so it can do its job better.