首页 > 其他 > 详细

Delphi函数参数中的陷阱

时间:2014-02-12 00:47:22      阅读:449      评论:0      收藏:0      [点我收藏+]
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;

begin
end.


调用方用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;
}


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

bubuko.com,布布扣

 

出错语句在DLL中

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


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

bubuko.com,布布扣

可以看到,函数返回值实际上是一个隐式的参数,是一个二级指针。在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;
}


 

Delphi函数参数中的陷阱

原文:http://blog.csdn.net/aqtata/article/details/19079737

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!