GCC error: Cannot apply offsetof to member function MyClass::MyFunction

人走茶凉 提交于 2019-12-23 22:25:29

问题


After trying to replace the offset keyword with __offsetof while trying to compile with Apple GCC 4.2.1 using the -fasm-blocks argument (which enables Intel style assembly syntax) inline assembly code which worked in MSVC, I get an error: Cannot apply offsetof to member function MyClass::MyFunction

class MyClass
{
    void MyFunction(void* pData)
    {

    }
};

void test()
{
    _asm
    {
        //mov eax, offset MyClass::MyFunction - this works in MSVC
        mov eax, offsetof(class MyClass, MyFunction) //error: Cannot apply offsetof to member function MyClass::MyFunction
        mov eax, __offsetof(class MyClass, MyFunction) //error: Invalid cast from type 'void (MyClass::*)(void*)' to type size_t
    };
}


Can somebody please tell me, what should I do? It seems that the whole structure of the application I'm porting is based on this damn offset macro...


回答1:


offsetof gets the offset of a member from the start of a structure, but functions are not members in that sense (not even virtual functions). what you are probably after is the offset keyword:

class A
{
    int Func1()
    {
        return 1;
    }
};

__declspec(naked) int GetAddress()
{
    __asm
    {
        mov eax, offset A::Func1
        retn
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    printf("0x%08X\n",GetAddress());
    return 0;
}

To get the same effect under GCC (I'm using -masm=intel, as -fasm-blocks is apple only) we would do (32bit exe, tested under windows 7 64bit, using GCC 4.4):

class A
{
public:
    int Func1() __attribute__((noinline))
    {
        return 1;
    }
};

int a = 0; //this is bad, but it works for this demo
int GetAddress()// __attribute__((noinline))
{
    __asm("mov dword ptr[_a], offset __ZN1A5Func1Ev");
    return a;
}

int main()
{
    A a;
    printf("%d\n",a.Func1());
    system("pause");
    printf("0x%08X\n",GetAddress());
    return 0;
}

The problem with GCC is that:

  1. you can't bind to auto-inlined functions, as no symbol is generated (hence the noinline).
  2. you need to bind to decorated symbols unless you force undecorated symbols (and even then there will still be some decoration)



回答2:


Try this:

mov eax, MyClass::MyFunction

What does it say?

PS: In old Intel syntax, this would have to be something like

mov eax, DWORD PTR MyClass::MyFunction

I don't know whether the gcc asm-block feature requires this or not.




回答3:


Since you said you don't need to hardcode it, just fetch the address in C++ code:

void test(){
  typedef void (MyClass::*memfun)(void*);
  memfun f = &MyClass::MyFunction;
  __asm{
    // I don't know why lea, but all forms of mov where failing. :|
    lea eax, dword ptr [x];
    call dword ptr [eax]; // test call, if the jump succeeds, you're done. :)
  }
}



回答4:


You cannot use offsetof with member functions, only with data members. It makes no sense. Member functions are not actually stored in the class.



来源:https://stackoverflow.com/questions/6227256/gcc-error-cannot-apply-offsetof-to-member-function-myclassmyfunction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!