今天遇到一段代码,
C++的写法是
IClassFactory* pFactory = NULL;
pFactory->CreateInstance( NULL, riid, ppv);这里的IClassFactory这个interface在c++和delphi里都有定义,createinterface的三个参数具体是什么东西可以不用管它我翻译成delphi如下:
type piclassfactory=^iclassfactory;
var pfactory:piclassfactory;
pfactory.CreateInstance(nil,riid,ppv); 或 pfactory^.CreateInstance(nil,riid,ppv)这两种写法在用反汇编软件看的时候,结果是一样的。但是实际调试时发现
delphi的写法有问题
如c++的代码编译完后应该是
.text:004F1728 10C mov esi, esp
.text:004F172A 10C mov eax, [ebp+arg_C]
.text:004F172D 10C push eax
.text:004F172E 110 mov ecx, [ebp+arg_8]
.text:004F1731 110 push ecx
.text:004F1732 114 push 0
.text:004F1734 118 mov edx, [ebp+pfactory]
.text:004F1737 118 mov eax, [edx]
.text:004F1739 118 mov ecx, [ebp+pfactory]
.text:004F173C 118 push ecx
.text:004F173D 11C mov edx, [eax+0Ch]
.text:004F1740 11C call edx
但是delphi编译出来的确是
.text:0045A20A 020 lea eax, [ebp+arg_0] ; Load Effective Address
.text:0045A20D 020 push eax
.text:0045A20E 024 mov eax, [ebp+var_8]
.text:0045A211 024 push eax
.text:0045A212 028 push 0
.text:0045A214 02C mov eax, [ebp+pfactory]
.text:0045A217 02C mov eax, [eax] //这句多余
.text:0045A219 02C push eax
.text:0045A21A 030 mov eax, [eax] //这句多余
.text:0045A21C 030 call dword ptr [eax+0ch]其中delphi带不带^运算符编译出来的是一样的,十分奇怪,也就是说delphi多了一次多余的[eax]操作,不知我翻译的写法问题出在哪?
C++的写法是
IClassFactory* pFactory = NULL;
pFactory->CreateInstance( NULL, riid, ppv);这里的IClassFactory这个interface在c++和delphi里都有定义,createinterface的三个参数具体是什么东西可以不用管它我翻译成delphi如下:
type piclassfactory=^iclassfactory;
var pfactory:piclassfactory;
pfactory.CreateInstance(nil,riid,ppv); 或 pfactory^.CreateInstance(nil,riid,ppv)这两种写法在用反汇编软件看的时候,结果是一样的。但是实际调试时发现
delphi的写法有问题
如c++的代码编译完后应该是
.text:004F1728 10C mov esi, esp
.text:004F172A 10C mov eax, [ebp+arg_C]
.text:004F172D 10C push eax
.text:004F172E 110 mov ecx, [ebp+arg_8]
.text:004F1731 110 push ecx
.text:004F1732 114 push 0
.text:004F1734 118 mov edx, [ebp+pfactory]
.text:004F1737 118 mov eax, [edx]
.text:004F1739 118 mov ecx, [ebp+pfactory]
.text:004F173C 118 push ecx
.text:004F173D 11C mov edx, [eax+0Ch]
.text:004F1740 11C call edx
但是delphi编译出来的确是
.text:0045A20A 020 lea eax, [ebp+arg_0] ; Load Effective Address
.text:0045A20D 020 push eax
.text:0045A20E 024 mov eax, [ebp+var_8]
.text:0045A211 024 push eax
.text:0045A212 028 push 0
.text:0045A214 02C mov eax, [ebp+pfactory]
.text:0045A217 02C mov eax, [eax] //这句多余
.text:0045A219 02C push eax
.text:0045A21A 030 mov eax, [eax] //这句多余
.text:0045A21C 030 call dword ptr [eax+0ch]其中delphi带不带^运算符编译出来的是一样的,十分奇怪,也就是说delphi多了一次多余的[eax]操作,不知我翻译的写法问题出在哪?
解决方案 »
- 新发布一个免费软件,大家给点意见
- socket通信出错:"远程主机强迫关闭了一个现有的连接"
- 怎么写格式化程序
- 打印的一个小问题
- DBGridEH怎么去表头?设置哪个属性
- 不好意思,用installshield express 还是不会打包脱离delphi环境的执行程序,还有就是怎样将bde 这个数据环境一块打包进去,请各位指点一下!
- 高手,高手,我看见你了,请进...
- 请问什么是奇效验,什么偶效验,怎么实现
- 谁有能将一个字符串的字符依次显示在窗体或其他控件上如PANEL!!!!???
- dbgrideh 控件怎么将指定单元格数据导出到EXCEL中指定工作表的指定位置
- 判断数据集状态
- PageControl1 多个tabsheet选中问题
接口Iclassfactory类型在Delphi中本身就是指针类型,相当于C++的IClassFactory*,你再定义:
piclassfactory=^iclassfactory;
就是指针的指针了,既然是指针的指针类型,肯定要多取一次值了:
.text:0045A214 02C mov eax, [ebp+pfactory]
.text:0045A217 02C mov eax, [eax]
另外问一下是vc里面可以用这种方法去定义并访问一个借口,以itest为例
CComPtr<Itest> m_test;
CreateInstance( NULL, riid, (void**)&m_test);那么转成delphi该是什么呢?
这里的Itest是个接口名,riid可以不管我写成
var
m_test:itest;
CreateInstance(nil,riid,@m_test);
不知道对不对
还有就是上面vc的那种定义方法
CComPtr<Itest> m_test;
实际上是生成了itest接口的一个实例对象
而delphi的var m_test:itest呢?是定义了一个指针但是没有内容?
这两种语言生成的m_test是一样的么?
....
end;使用接口时:
var
test: Itest;
begin
test := TTest.Create;
test.xxxx
end;
如果事先不知道TTest是否有Itest的实现代码,可以进行判断:
var
Obj: TTest;
test: Itest;
begin
Obj := TTest.Create;
if Supports(Obj, Itest, test) then
test.xxxx
end;
但是重写过程中发现很多不好实现的地方
例如vc的interface实际上就是class,而delphi的接口就是指针。等等这是Createinstancefromdll的代码
HINSTANCE CreateInstanceFromDll(LPCTSTR lpDllName, REFCLSID rclsid, REFIID riid, LPVOID * ppv)
{
(*ppv) = NULL; HINSTANCE hDll = LoadLibrary( lpDllName );
if ( NULL == hDll )
{
return NULL;
} typedef HRESULT (__stdcall *GETCLASS_PROC)(REFCLSID,REFIID,LPVOID*); GETCLASS_PROC procGetClassObject = (GETCLASS_PROC)GetProcAddress( hDll, "DllGetClassObject" ); if( procGetClassObject )
{
IClassFactory* pFactory = NULL; HRESULT hr = procGetClassObject(rclsid, IID_IClassFactory, (void**)&pFactory);
if( pFactory )
{
hr = pFactory->CreateInstance( NULL, riid, ppv); pFactory->Release();
pFactory = NULL; if( NULL == *ppv )
{
FreeLibrary( hDll );
return NULL;
}
}
else
{
FreeLibrary( hDll );
return NULL;
}
}
else
{
FreeLibrary( hDll );
return NULL;
} return hDll;
}
调用的时候
CreateInstanceFromDll(_T("test.dll"), CLSID_test, IID_Itest, (void**)&m_test);
其中m_test就是itest类型的实例
这是vc的做法,转成delphi,我发现问题多多
test := nil;即可
以下是我的翻译后的delphi代码
function CreateInstanceFromDll(lpDllname:pansichar;var rclsid:TGUID;var riid:TGUID;ppv:PPointer):hwnd;
var
hDll:hwnd;
pFactory:iclassfactory;
hr:hresult;
procGetClassObject:function (var rclsid:TGUID;var riid:TGUID;ppv:PPointer):hresult;stdcall;
begin
ppv:=nil;
hdll:=loadlibrary(lpdllname);
if 0=hdll then
begin
result:=0;
end;
@procGetClassObject:=GetProcAddress(hdll,'DllGetClassObject');
if not(@procGetClassObject = nil) then
begin
pfactory:=nil;
hr:=procgetclassobject(rclsid,IID_IClassFactory,ppointer(@pfactory));
if pfactory<>nil then
begin
hr:=pfactory.CreateInstance(nil,riid,ppv); //这里的函数调用结果不对,vc下ppv调用后是获得了返回值的,而delphi这个翻译代码获得的是nil
pfactory:=nil;
if ppv=nil then
begin
freelibrary(hdll);
result:=0;
end;
end
else
begin
freelibrary(hdll);
result:=0;
end;
end
else
begin
freelibrary(hdll);
result:=0;
end;
end;调用的时候采用
Createinstancefromdll(testdll',CLSID_test,IID_Itest,ppointer(&m_test));
但是在我标注的那个地方出错了
如果你不想动里面的代码,把函数说明改一改:
function CreateInstanceFromDll(lpDllname:pansichar;var rclsid:TGUID;var riid:TGUID;var ppv:Pointer):hwnd;procGetClassObject:function (var rclsid:TGUID;var riid:TGUID;var ppv:Pointer):hresult;stdcall;