Delphi 如何调用 VC 的类的成员函数?
比如下面 VC 的代码:
class ITestObj
{
public:
int MyAdd(int a, int b)
{
return a + b;
}
void ShowMSG()
{
::MessageBoxA(0, (LPCSTR)"Delphi 调用 VC 类的成员函数", (LPCSTR)"系统提示:", MB_OK);
}
};
我们如何才能在 Delphi 中调用 ITestObj 类的成员函数 MyAdd 和 ShowMSG 呢?
用一个一个导出为 C 类型函数的方式,实在是太麻烦了。如果比较大的类,就不太实用了。
还有一种方法,使用虚函数。把上面的代码修改如下:
class ITestObj
{
public:
virtual int __stdcall MyAdd(int a, int b) // 定义;必须是 stdcall 方式
{
return a + b;
}
virtual void __stdcall ShowMSG()
{
::MessageBoxA(0, (LPCSTR)"Delphi 调用 VC 类的成员函数", (LPCSTR)"系统提示:", MB_OK);
}
};
添加了 virtual 和 __stdcall 修饰符。这样这个类的成员函数就变成了类的虚函数了。
这样,我们就可以在 Delphi 中访问这个类的虚函数了。
但有一点,类必须首先要实例化。Delphi 中肯定是无法做到的,这个必须放在 VC 中。
所以必须添加 C 类型导出函数,实现类的实例化。
#define TEST_API extern "C" _declspec(dllexport)
ITestObj* pTest = NULL;
// 类的实例化;C 类型函数导出
TEST_API ITestObj* CreateTestObj()
{
pTest = new ITestObj();
return pTest;
}
// 销毁类的实例;C 类型函数导出
TEST_API void DestoryTestObj()
{
delete pTest;
}
这样 VC 部分就可以了,不用再做其它的工作了。
这样这个 Dll 输出了两个函数:CreateTestObj 和 DestoryTestObj,实现类的实例化和销毁。
Delphi 部分:
1、先对 ITestObj 类进行申明:
type
ITestObj = class(TObject)
protected
function vmMyAdd(a, b: Integer): Integer; virtual; abstract; // VC 的虚函数;顺序必须和 VC 中的一致
procedure vmShowMSG(); virtual; abstract; // VC 的虚函数;顺序必须和 VC 中的一致
public //
function MyAdd(a, b: Integer): Integer; stdcall; // 必须为 stdcall 类型
procedure ShowMSG(); stdcall; // 必须为 stdcall 类型
end;
2、导出函数声明:
function CreateTestObj: ITestObj; stdcall; external 'TestObj.dll';
procedure DestoryTestObj; stdcall; external 'TestObj.dll';
3、ITestObj 类的实现:
procedure vcVMTFuncCall(const intVMTFuncOffsetAddr: Integer); register; ASSEMBLER;
asm
POP EBP
POP EDX
POP ECX
PUSH EDX
SUB ESP, 4
MOV EDX, [ECX]
JMP [EDX + intVMTFuncOffsetAddr]
end;
function ITestObj.MyAdd(a, b: Integer): Integer;
asm
MOV EAX, VMTOFFSET vmMyAdd
JMP vcVMTFuncCall
end;
procedure ITestObj.ShowMSG;
asm
MOV EAX, VMTOFFSET vmShowMSG
JMP vcVMTFuncCall
end;
这样就OK了,可以调用了。
4、调用:
比如:
Caption := Format('3 + 2 = %d', [CreateTestObj.MyAdd(3, 2)]);
DestoryTestObj;
再比如:
CreateTestObj.ShowMSG;
DestoryTestObj;
我称之为虚函数模式。下一篇文章,https://blog.youkuaiyun.com/dbyoung/article/details/113482865 使用内存的方式,直接在 Delphi 中调用 VC 的类的成员函数。