Visual C++ 6.0のDLLをDelphiから呼び出す
Visual C++ 6.0で作ったDLLを呼び出すときは、WIN32 APIのLoadLibararyとGetProcAddressを使います。この方法は、C++ Builderやその他の処理系で作ったDLLの呼び出しにも使える一般的な方法です。
LoadLibrary関数とは
LoadLibraryはDLLのパス名を引数として、そのインスタンスハンドルを返す関数です。DLLのロードに失敗するとインスタンスハンドルはNULL(=0)になります。アプリケーションと同じフォルダにDLLがあるときは、パス名はファイル名だけでOKですが、Windowsフォルダにあるときは、GetWindowsDirectory関数でWindowsフォルダを求めて振るパスを指定します。
DLL関数が不要になったらFreeLibrary関数を呼び出してDLLを解放します。
GetProcAddressとは
GetProcAddressはDLL内の関数名からその関数へのポインタを取得します。
関数ポインタの宣言
関数ポインタの宣言はつぎのように行います。StdCall属性を付けるのを忘れないでください。
type
TFuncPtr = function (引数の並び): 戻り値の型; StdCall;
var
FuncPtr : TFuncPtr;
サンプルプログラム
(Delphi)
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
btnFunc1: TButton;
btnProc1: TButton;
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Edit2: TEdit;
Label3: TLabel;
Edit3: TEdit;
Edit4: TEdit;
procedure FormCreate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure btnFunc1Click(Sender: TObject);
procedure btnProc1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
type
TFunc1 = function (x: Longint) : Longint; StdCall;
TProc1 = procedure (pBuff: PByte; n: Integer); StdCall;
var
Func1: TFunc1;
Proc1: TProc1;
hModule: Longint;
procedure TForm1.FormCreate(Sender: TObject);
var
pProc: Pointer;
begin
hModule := LoadLibrary('SampDll.dll');
if hModule = 0 then
begin
MessageDlg('DLLをロードできない。', mtError, [mbOK], 0);
Exit;
end;
pProc := GetProcAddress(hModule, 'Func1');
if pProc = nil then
begin
MessageDlg('Func1のアドレスが取得できない。', mtError, [mbOK], 0);
Exit;
end;
Func1 := pProc;
pProc := GetProcAddress(hModule, 'Proc1');
if pProc = nil then
begin
MessageDlg('Func1のアドレスが取得できない。', mtError, [mbOK], 0);
Exit;
end;
Proc1 := pProc;
end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if hModule <> 0 then
FreeLibrary(hModule);
end;
procedure TForm1.btnFunc1Click(Sender: TObject);
var
X, Y: Longint;
begin
X := StrToInt(Edit1.Text);
Y := Func1(X);
Edit2.Text := IntToStr(Y);
end;
procedure TForm1.btnProc1Click(Sender: TObject);
var
n, i: Integer;
pBuff, p: PByte;
s: String;
begin
n := StrToInt(Edit3.Text);
pBuff := AllocMem(n);
Proc1(pBuff, n);
s := '';
p := pBuff;
for i := 0 to n - 1 do
begin
s := s + IntToHex(p^, 2) + ' ';
Inc(p);
end;
Edit4.Text := s;
FreeMem(pBuff);
end;
end.
(Visual C++)
// SampDll.cpp : DLL アプリケーション用のエントリ ポイントを定義します。
//
#include "stdafx.h"
extern "C" void WINAPI Proc1(BYTE* pBuff, int n);
extern "C" long WINAPI Func1(long x);
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//////////////////////////////////////////////////////////////////
void WINAPI Proc1(PBYTE pBuff, int n)
{
int i;
PBYTE p = pBuff;
for (i = 0; i < n; i++)
{
*p = (BYTE)0xff;
p++;
}
}
long WINAPI Func1(long x)
{
return (2 * x + 1);
}