Ошибка GCC: невозможно применить offsetof к функции-члену MyClass :: MyFunction - PullRequest
2 голосов
/ 03 июня 2011

После попытки заменить ключевое слово offset на __ offsetof при попытке компиляции с Apple GCC 4.2.1 с использованием -fasm-blocks аргумент (который включает Intel style синтаксис сборки) встроенного кода сборки, который работал в MSVC, я получаю сообщение об ошибке: Невозможно применить offsetof к функции-члену 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
    };
}


Может кто-нибудь сказать, пожалуйста, что мне делать? Кажется, что вся структура приложения, которое я портирую, основана на этом чертовом смещении макросе ...

Ответы [ 4 ]

2 голосов
/ 03 июня 2011

offsetof получает смещение элемента с начала структуры, но функции в этом смысле не (даже виртуальные функции). то, что вы, вероятно, после, это ключевое слово offset:

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;
}

Чтобы получить тот же эффект в GCC (я использую -masm = intel, так как -fasm-blocks - только apple), мы бы сделали (32-битный exe, протестирован под Windows 7, 64-битный, используя 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;
}

Проблема с GCC заключается в том, что:

  1. Вы не можете связать с автоматически встроенными функциями, так как символ не генерируется (следовательно, нет строки).
  2. вам нужно привязать к декорированным символам, если вы не навязываете непокрашенные символы (и даже тогда будет какое-то украшение)
1 голос
/ 03 июня 2011

Попробуйте:

mov eax, MyClass::MyFunction

Что это говорит?

PS: в старом синтаксисе Intel это должно быть что-то вроде

mov eax, DWORD PTR MyClass::MyFunction

Iне знаю, требуется ли это для функции gcc asm-block.

0 голосов
/ 03 июня 2011

Вы не можете использовать offsetof с функциями-членами, только с данными-членами. Это не имеет никакого смысла. Функции-члены на самом деле не хранятся в классе.

0 голосов
/ 03 июня 2011

Поскольку вы сказали, что вам не нужно жестко его кодировать, просто получите адрес в коде C ++:

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. :)
  }
}
...