https://blog.youkuaiyun.com/dbyoung/article/details/94576926 这篇文章中,
调用 VC 的 C++ Class 类导出的 DLL 函数时,需要在 VC 中,对对象进行实例化。
不在 VC 中实例化,在 Delphi 实例化可不可行?答案是肯定的。
譬如 C++ Class Dll:
// 这是已导出类的构造函数。
CppDll::CppDll()
{
return;
}
int CppDll::MyAdd(int a, int b)
{
return a + b;
}
void CppDll::ShowMSG()
{
::MessageBoxA(0, (LPCSTR)"Delphi 调用 VC 类的成员函数", (LPCSTR)"系统提示:", MB_OK);
}
用 depends 查看导出函数
x86:
public: __thiscall CppDll::CppDll(void)
public: class CppDll & __thiscall CppDll::operator=(class CppDll &&)
public: class CppDll & __thiscall CppDll::operator=(class CppDll const &)
public: int __thiscall CppDll::MyAdd(int,int)
public: void __thiscall CppDll::ShowMSG(void)
x64:
public: __cdecl CppDll::CppDll(void) __ptr64
public: class CppDll & __ptr64 __cdecl CppDll::operator=(class CppDll && __ptr64) __ptr64
public: class CppDll & __ptr64 __cdecl CppDll::operator=(class CppDll const & __ptr64) __ptr64
public: int __cdecl CppDll::MyAdd(int,int) __ptr64
public: void __cdecl CppDll::ShowMSG(void) __ptr64
第一个为类的构造函数(thiscall,cdecl,是 VC 默认的调用约定,当然可以自行修改)。
最后两个是 C++ Class 类导出的函数,我们希望在 Delphi 中调用的(x86 与 x64 的函数导出是有细微差别的)。
Delphi 中,先对函数进行申明:
{$IFDEF WIN32}
function CreateCppClass: Pointer; stdcall; external 'vcd.dll' name '??0CppDll@@QAE@XZ'; // 创建 C++ 类
function CppClass_MyAdd(a, b: Integer): Integer; stdcall; external 'vcd.dll' name '?MyAdd@CppDll@@QAEHHH@Z'; // C++ 类的导出函数 MyAdd
procedure CppClass_ShowMSG; stdcall; external 'vcd.dll' name '?ShowMSG@CppDll@@QAEXXZ'; // C++ 类的导出函数 ShowMSG
{$ELSE}
function CreateCppClass: Pointer; cdecl; external 'vcd.dll' name '??0CppDll@@QEAA@XZ'; // 创建 C++ 类
function CppClass_MyAdd(a, b: Integer): Integer; cdecl; external 'vcd.dll' name '?MyAdd@CppDll@@QEAAHHH@Z'; // C++ 类的导出函数 MyAdd
procedure CppClass_ShowMSG; cdecl; external 'vcd.dll' name '?ShowMSG@CppDll@@QEAAXXZ'; // C++ 类的导出函数 ShowMSG
{$ENDIF}
先实例化类(先定义一个成员变量:FCppClassObj: Pointer):
GetMem(FCppClassObj, 8);
FCppClassObj := CreateCppClass;
封装一下调用:
function TForm1.MyAdd({$IFDEF WIN32}a, b: Integer; pObj: Pointer{$ELSE}pObj: Pointer; a, b: Integer {$ENDIF}): Integer;
begin
Result := CppClass_MyAdd(a, b);
end;
procedure TForm1.ShowMSG({$IFDEF WIN32}R1, R2: Integer; {$ENDIF} pObj: Pointer);
begin
CppClass_ShowMSG;
end;
这样类就实例化完成了。下面我们就可以调用类的导出函数了:
{$IFDEF WIN32}
Caption := IntToStr(MyAdd(4, 6, FCppClassObj));
ShowMSG(0, 0, FCppClassObj);
{$ELSE}
Caption := IntToStr(MyAdd(FCppClassObj, 4, 6));
ShowMSG(FCppClassObj);
{$ENDIF}
OK,成功!
因为使用了内存的方式,在 Delphi 中进行了 C++ Class 的实例化。所以我称之为内存模式。
测试源码:https://github.com/dbyoung720/DCallCppClassDll.git
测试环境: WIN10X64+Delphi10.3+VS2019