delphi.gif (306 バイト) Visual C++ 6.0のDLLをDelphiから呼び出す


Visual C++ 6.0で作ったDLLを呼び出すときは、WIN32 APIのLoadLibararyとGetProcAddressを使います。この方法は、C++ Builderやその他の処理系で作ったDLLの呼び出しにも使える一般的な方法です。

toach.gif (917 バイト) LoadLibrary関数とは
 LoadLibraryはDLLのパス名を引数として、そのインスタンスハンドルを返す関数です。DLLのロードに失敗するとインスタンスハンドルはNULL(=0)になります。アプリケーションと同じフォルダにDLLがあるときは、パス名はファイル名だけでOKですが、Windowsフォルダにあるときは、GetWindowsDirectory関数でWindowsフォルダを求めて振るパスを指定します。
  DLL関数が不要になったらFreeLibrary関数を呼び出してDLLを解放します。

 

toach.gif (917 バイト) GetProcAddressとは
 GetProcAddressはDLL内の関数名からその関数へのポインタを取得します。

 

toach.gif (917 バイト) 関数ポインタの宣言
 関数ポインタの宣言はつぎのように行います。StdCall属性を付けるのを忘れないでください。

type
  TFuncPtr = function (引数の並び): 戻り値の型; StdCall;

var
  FuncPtr : TFuncPtr;

 

delphi1.gif (322 バイト) サンプルプログラム
(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);
}