ポインタについて


DelDel  2007-09-06 07:27:44  No: 27672

あるC言語で作成されたDLLの関数を使用するとアドレスの配列が返されます。
DLL内ではchar***,unsigned int*で定義されています。

このアドレスをIntegerで受け取り、+4バイトした値のアドレスの中身にアクセスし、配列の中身をすべて取得したいのですが方法がわかりません。

どなたかお教えください。


AVA  2007-09-07 02:34:06  No: 27673

DLLの内容が不明なのでとりあえずパラメータなしでDLL中の関数名をGetAddressと想定して

implementation

type
  TAbc = function : integer; stdcall;

ボタンクリックしたときのイベントとして
procedure TForm1mButton1Click(Sender: TObject);
var
  DllHandle: THandle;
  Abc: TAbc;
  APos: integer;
begin
  DllHandle := LoadLibrary('ABC.DLL');  //DLL呼び出し
  if DllHandle < 32 then  //エラーコードはWin32Apiを参照してネ
    raise DllError.Create('ABC.DLLが見つかりません');
  @Abc := GetProcAddeess(DllHandle, 'GetAddress'); //関数セット
  if @Abc = nil then
    raise DllError.Create('GetAddressが見つかりません');
  APos := Abc;  //DLLのGetAddressを実行
  FreeLibrary(DllHandle);
end;

これでDLLからポインターのIntegerを取得できると思うのですが。


DelDel  2007-09-07 05:06:27  No: 27674

AVAさま
ありがとうございます。

早速、教えていただいたDLLの動的リンクで試すにあたって、Win32APIのSleep関数を呼び出そうとしたのですが、なぜか、関数のハンドルはGetできたのですが実行すると固まってしまいます。

※ソース
implementation

type
  TAbc = procedure Sleep( milSec : integer); stdcall;

procedure TestDllDynLoadFunc;
  DllHandle: THandle;
  Abc: TAbc;
begin
 try

   //kernel32.DLL呼び出し
   DllHandle := LoadLibrary('kernel32.DLL');  
   if DllHandle = 0 then  
   begin
    //エラーコードはWin32Apiを参照してネ
    raise DllError.Create('kernel32.DLLが見つかりません');
   end;

   //関数セット
   @Abc := GetProcAddeess(DllHandle, 'Sleep'); 
   if @Abc = nil then
   begin
    raise DllError.Create('Sleepが見つかりません');
   end;

   //DLLのSleepを実行すると固まる…><
   Abc(5000);  

 finally
  if DllHandle <> 0 then
  begin
   FreeLibrary(DllHandle);
  end;
 end;
end;

<DLLの内容が不明なのでとりあえずパラメータなしでDLL中の関数名を<GetAddressと想定して

DLLの内容は出力可能なプリンタの一覧を返す関数が入っています。第一引数char***のほうにプリンタ一覧が返ってくるのですが、
char***なんて配列をDelphiでどう定義してどのように渡したら良いのか
分からないので、配列の先頭アドレスから順々にアクセスしようとか
考えています。
(ちなみに.NETだとStringBuilderクラスを引数にすればできます)


AVA  2007-09-07 17:25:27  No: 27675

すみませんDllErrorの宣言を忘れてました。
  public
    {public宣言}
  end;

  DllError = class(Exception); ←これを入れる

var
  Form1: TForm1;

implementation

ところでプリンターの一覧を取得するのにDLLを使用する必要はあるのですか?
usesにPrintersを追加して

Printer.Printers

とやればプリンターの一覧を取得できますが。


DelDel  2007-09-08 02:12:58  No: 27676

<すみませんDllErrorの宣言を忘れてました。

コンパイルが通らないのでDllErrorの宣言は行ないました。
だけど、Sleep関数で処理が返ってきません・・・orz
そもそもSleep関数等のWindows.pasに定義されている関数は
呼び出すことはダメなのでしょうか?
(VC++で作成された自作DLLの関数呼び出しはOKだったので・・・)

<ところでプリンターの一覧を取得するのにDLLを使用する必要はあるのですか?

システム全体の仕様上そのDLLを使用しないと、
プリンタの一覧取得だけでなく印刷処理等も行えないのです。
char***で宣言されている関数呼び出しの場合は何を渡せば良いのか
非常に悩んでいます。
どうかご教授ください。。。。。


ポインタ  2007-09-08 04:02:17  No: 27677

理解するために.....
h ttp://itpro.nikkeibp.co.jp/article/COLUMN/20061206/256198/


AVA  2007-09-11 02:07:24  No: 27678

Sleepの動的呼び出しはちゃんと動作したのにと悩んでいたのですがわかりました
TAbc = procedure Sleep( milSec : integer); stdcall;

TAbc = procedure (milSec: integer); stdcall;
にしてください。


TOBY  URL  2007-09-12 01:08:43  No: 27679

結局のところ、DLL側の仕様がわからないと
なんとも言えなくないですか?

char***は、宣言だけなら、PCharのポインタののポインタですから、
type
  PPChar = ^PChar; 
  PPPChar = ^PPChar; 
ですが、
それを渡すと言うことは、あらかじめ、配列を確保して渡すわけで、

PCharが文字列と考えると、その配列の配列?になるんでしょうか。
つまり、文字列の2次元配列でしょうか。
とりあえず、与えられた情報では、ここまでしか分からんです。

どれくらい配列を確保しなければいけないのか、とかは、与えられた仕様によりけりでしょうし。

結局は、仕様がわからんと、わからんという話に……。

と、私もポインタに関しては、あいまいなので、識者の方つっこんでください。


pekesuke  2007-09-12 05:01:48  No: 27680

type
  TAList = array[0..2] of array[0..255] of PAnsiChar;
  TAbc = function (var FList: TAList): integer; stdcall;

ボタンクリックしたときのイベントとして
procedure TForm1mButton1Click(Sender: TObject);
var
  DllHandle: THandle;
  Abc: TAbc;
  APos: integer;
  FList: TAList;
begin
  DllHandle := LoadLibrary('ABC.DLL');  //DLL呼び出し
  if DllHandle < 32 then  //エラーコードはWin32Apiを参照してネ
    raise DllError.Create('ABC.DLLが見つかりません');
  @Abc := GetProcAddeess(DllHandle, 'GetAddress'); //関数セット
  if @Abc = nil then
    raise DllError.Create('GetAddressが見つかりません');
  APos := Abc(FList);  //DLLのGetAddressを実行
  FreeLibrary(DllHandle);
end;

かな?


DelDel  2007-09-13 07:13:21  No: 27681

返事が遅くなり大変申し訳ございません。

AVAさま。
当方のミスでした。stdcallを付けていませんでした。
Sleep関数は無事に呼び出すことができました。

TOBYさま
DLL側の仕様しましては、

int GetPrtAddress( char*** prtInf,int* size,int* Num );

第1引数:プリンタ名一覧
第2引数:prtInfで確保した領域のサイズ
第3引数:プリンタ名一覧件数
戻り値 :0で成功、0以外は失敗
です。

pekesukeさま
TAList = array[0..2] of array[0..255] of PAnsiChar;
を使用して呼び出して見ましたが、うまく動きませんでした。
配列数に関しては、第3引数に格納されるのでそれを利用しようと
考えてるので宣言時は適当な数で宣言しました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加