鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > delphi > >

Delphi函数参数中的陷阱

来源:互联网 作者:佚名 时间:2015-07-05 21:29
function abc(A: Integer): Integer; 这是一个Delphi的函数声明,看上去很简单,只有一个参数而已,但是真实情况呢?在编译成二进制代码后,实际上函数的参数已经有3个了! 为了更详细的说明问题,先用Delphi写一个DLL,导出一个接口,接口有一个Show方法。

   

function abc(A: Integer): Integer;

    这是一个Delphi的函数声明,看上去很简单,只有一个参数而已,但是真实情况呢?在编译成二进制代码后,实际上函数的参数已经有3个了!

    为了更详细的说明问题,先用Delphi写一个DLL,导出一个接口,接口有一个Show方法。

library Project1;uses  Windows;{$R *.res}type  ITest = interface    procedure Show(); stdcall;  end;  TTest = class(TInterfacedObject, ITest)  public    procedure Show(); stdcall;  end;function GetTest: ITest; stdcall;begin  Result := TTest.Create;end;exports  GetTest;{ TTest }procedure TTest.Show;begin  OutputDebugString('Hello World');end;beginend.

    调用方用C++编写

#include "stdafx.h"#include<iostream>#include<Windows.h>interface ITest : public IUnknown{	virtual void __stdcall show() = 0;};typedef ITest* (WINAPI *GetITest)();int _tmain(int argc, _TCHAR* argv[]){	HMODULE h = LoadLibrary(TEXT("Project1.dll"));	if (h != 0)	{		GetITest get = (GetITest)GetProcAddress(h, "GetTest");		ITest *test = get();		test->show();		test->Release();	}	system("pause");	return 0;}

    运行后直接弹出一个内存错误

    /

    出错语句在DLL中

function GetTest: ITest; stdcall;begin  Result := TTest.Create;end;

    以反汇编代码的形式查看这个函数就能发现问题

    /

    可以看到,函数返回值实际上是一个隐式的参数,是一个二级指针。在Dephi中使用不会发现问题,因为它自动作出了优化。

    而在混合编程中,这样直接返回一个接口或对象的时候就会出现内存为空的错误。

    修改后的调用代码

#include "stdafx.h"#include<iostream>#include<Windows.h>interface ITest : public IUnknown{	virtual void __stdcall show() = 0;};// 正确的函数原型typedef VOID (WINAPI *GetITest)(ITest**);int _tmain(int argc, _TCHAR* argv[]){	HMODULE h = LoadLibrary(TEXT("Project1.dll"));	if (h != 0)	{		GetITest get = (GetITest)GetProcAddress(h, "GetTest");				// 修改后的调用方法		ITest *test = nullptr;		get(&test);		test->show();		test->Release();	}	system("pause");	return 0;}

网友评论
<