thiscall в FPC в явном виде не используется, но он неявно возникает при импорте классов, написанных на c++, например при работе с OpenOffice. Импорт отдельных методов из dll-файла есть более гибкое решение, чем использование ключевого слова cppclass.
Наример, есть класс написанный на c++
- Код: Выделить всё
class __declspec(dllexport) Foo
{
public:
Foo()
{
i = 0;
cout<<"create"<<endl;
}
~Foo()
{
cout<<"death"<<endl;
}
void inc()
{
i++;
cout<<"increment"<<endl;
}
void print()
{
cout<<"value is "<<i<<endl;
}
private:
int i;
};
С помощью утилиты dumpbin легко получить таблицу экспортируемых методов.
- Код: Выделить всё
0 00001AF0 ??0Foo@@QAE@XZ public: __thiscall Foo::Foo(void)
1 00001B20 ??1Foo@@QAE@XZ public: __thiscall Foo::~Foo(void)
2 000013D0 ??4Foo@@QAEAAV0@ABV0@@Z public: class Foo & __thiscall Foo::operator=(class Foo const &)
3 00001B60 ?inc@Foo@@QAEXXZ public: void __thiscall Foo::inc(void)
4 00001BA0 ?print@Foo@@QAEXXZ public: void __thiscall Foo::print(void)
Соответственно эти функции импортируются в программе на fpc:
- Код: Выделить всё
procedure FooCreate;stdcall;external 'wins.dll' name '??0Foo@@QAE@XZ';
procedure FooDestroy;stdcall;external 'wins.dll' name '??1Foo@@QAE@XZ';
procedure FooInc;stdcall;external 'wins.dll' name '?inc@Foo@@QAEXXZ';
procedure FooPrint;stdcall;external 'wins.dll' name '?print@Foo@@QAEXXZ';
c++ при вызове методов использует thiscall, соответственно это тот же stdcall но дополнительно в регистре ECX передается узаказтель на объект (this). Соответственно выполнение программы на fpc выглядит следующим образом:
- Код: Выделить всё
GetMem(this,size);
asm
MOV ECX, this
end;
FooCreate;
asm
MOV ECX, this
end;
FooInc;
asm
MOV ECX, this
end;
FooInc;
asm
MOV ECX, this
end;
FooPrint;
asm
MOV ECX, this
end;
FooDestroy;
FreeMem(this);
результат:
- Код: Выделить всё
create
increment
increment
value is 2
death