Delphi 如何调用 VC 的类的成员函数(一) --- 虚函数模式

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.csdn.net/dbyoung/article/details/113482865 使用内存的方式,直接在 Delphi  中调用 VC 的类的成员函数。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值