[Delphi:90255] Char**の移植

161 views
Skip to first unread message

Takefumi-o

unread,
Jan 30, 2008, 8:05:40 PM1/30/08
to Del...@users.gr.jp
こんにちは。太田と申します。


現在Cで書かれたヘッダをDelphiに移植しております。

そこに
int XDWAPI XDW_MergeXdwFiles(const char** lpszInputPaths, int nFiles,
const char* lpszOutputPath, void* reserved );

という関数があるのですが、このchar**の移植について悩んでいます。

lpszInputPathsには255バイト以内で複数のファイルのフルパス
nFilesには入力するファイルの個数
lpszOutputPathにはその複数のファイルを結合した結果ファイルの出力フルパス
reservedはダミーのヌル

を入力します。


とりあえず、char**の正確な移植方法がわかりませんのでPointerにして
実験しております。


■移植宣言

function XDW_MergeXdwFiles(const lpszInputPaths: Pointer; nFiles: Integer;
const lpszOutputPath: PChar; reserved: pointer): Integer; stdcall;


下記は実験コードです。

InFilesはTStringsで渡してきます。
MakeFileNameはStringです。


■テスト1

var
f: array[0..2] of pCHar;
begin
f[0] := PChar(InFiles[0]);
f[1] := PChar(InFiles[1]);
f[2] := PChar(InFiles[2]);
Result := XDW_MergeXdwFiles(@f, 3, PChar(MakeFileName), XDW_NULL);

としましたら成功しました。

■テスト2

var
f: array of pCHar;
begin
SetLength(f, InFiles.Count);

for i := 0 to InFiles.Count - 1 do
f[i] := pChar(InFiles[i]);

Result := XDW_MergeXdwFiles(@f, InFiles.Count, PChar(MakeFileName),
XDW_NULL);

としましたら失敗しました。
エラーコードは「パス名の指定が正しくない」です。
しかし、テスト1とまったく同じデータを渡しています。


テスト1と2では自分の中ではほぼ同等のデータが@fで
渡されていると思っているのですが、何が違うのでしょうか?

実際には渡してくるデータの個数がばらばらなので
できればテスト2を実用化したいと思います。

よろしくご教授ください。


---------------------------------
太田剛文
---------------------------------

高木太郎

unread,
Jan 30, 2008, 9:27:02 PM1/30/08
to Del...@ml.users.gr.jp
こんにちは、イマジオムの高木です。 いつもお世話になっております。

太田さん:

> ■テスト1
>
> var
> f: array[0..2] of pCHar;
> begin
> f[0] := PChar(InFiles[0]);
> f[1] := PChar(InFiles[1]);
> f[2] := PChar(InFiles[2]);

> Result := XDW_MergeXdwFiles(@f, 3, ...);


>
> としましたら成功しました。
>
> ■テスト2
>
> var
> f: array of pCHar;
> begin
> SetLength(f, InFiles.Count);
>
> for i := 0 to InFiles.Count - 1 do
> f[i] := pChar(InFiles[i]);
>

> Result := XDW_MergeXdwFiles(@f, InFiles.Count, ...);
>
> としましたら失敗しました。

> テスト1と2では自分の中ではほぼ同等のデータが@fで
> 渡されていると思っているのですが、何が違うのでしょうか?

 C言語からの型変換の問題ではありません。 静的配列と動的配列では
Delphi がメモリに格納する形式が違うのです。

 配列を F とします。 静的配列の場合、@F は最初の要素のアドレスを
指します。 F のインデックスが0から始まるのであれば、@F=@F[0] です。

 これに対して動的配列では、@F は最初の要素のアドレスを指さず、
「最初の要素のアドレスを指すポインタの置かれているアドレス」を
指しています。 ですので @F<>@F[0] です。 静的配列と同じように
するには、@F[0] と書けば良かったと思います。

 #これは、動的配列では SetLength が呼び出され、より大きい別のメモリ
  領域を確保しなければならない場面があることによる仕様です。

 ちなみに string 型についても同じようなことが言えます。 string[255]
などとすると静的配列になります。 string と string[255] で、@S=@S[0] に
なるかどうか試してみると、理解が深まると思います。
――――――――――――――――――――――――――――――――――――
株式会社イマジオム 代表取締役 高木太郎
〒316-0024 茨城県 日立市 水木町 1-11-10
電話:0294-28-0147
ファクシミリ:0294-28-0148
電子メール:tarou_...@imageom.co.jp
ホームページ:http://www.imageom.co.jp/


Takefumi-o

unread,
Jan 30, 2008, 10:31:31 PM1/30/08
to Del...@ml.users.gr.jp
太田です

> これに対して動的配列では、@F は最初の要素のアドレスを指さず、
> 「最初の要素のアドレスを指すポインタの置かれているアドレス」を
> 指しています。 ですので @F<>@F[0] です。 静的配列と同じように
> するには、@F[0] と書けば良かったと思います。
> #これは、動的配列では SetLength が呼び出され、より大きい別のメモリ
> 領域を確保しなければならない場面があることによる仕様です。

 なるほど~
 よくわかりました。

 array ofの動的配列は目には見えないですが裏では
 線形リストのようになっているのですね。
 その先頭ポインタのポインタという意味ですね。


 早速試してみます。

 ありがとうございました。

---------------------------------
太田剛文
---------------------------------

高木太郎

unread,
Jan 30, 2008, 11:15:32 PM1/30/08
to Del...@ml.users.gr.jp
こんにちは、イマジオムの高木です。

高木:


>> これに対して動的配列では、@F は最初の要素のアドレスを指さず、
>> 「最初の要素のアドレスを指すポインタの置かれているアドレス」を
>> 指しています。 ですので @F<>@F[0] です。 静的配列と同じように
>> するには、@F[0] と書けば良かったと思います。
>> #これは、動的配列では SetLength が呼び出され、より大きい別のメモリ
>> 領域を確保しなければならない場面があることによる仕様です。

太田さん:
>  array ofの動的配列は目には見えないですが裏では
>  線形リストのようになっているのですね。
>  その先頭ポインタのポインタという意味ですね。

 リストというよりも、静的配列へのポインタです。 静的配列とは、置かれる
メモリ上の場所に違いがありますが…… (動的配列の内容は、ヒープに
置かれます)

Takefumi-o

unread,
Jan 31, 2008, 12:38:49 AM1/31/08
to Del...@ml.users.gr.jp
太田です。

> リストというよりも、静的配列へのポインタです。 静的配列とは、置かれる
> メモリ上の場所に違いがありますが…… (動的配列の内容は、ヒープに
> 置かれます)

 理解が違っていました。
 ではSetLengthを使うとMMがヒープに静的配列を作成し、
 そのポインタがarray of の変数に代入される、ということですね。


 話は戻りまして最初の質問は見事解決しました。

 @f[0]で渡して成功しまして、そのあと高木さんの話を参考に
 そのままfを渡しましたら、それも動作しました。

 ありがとうございました。

---------------------------------
太田剛文
---------------------------------

Reply all
Reply to author
Forward
0 new messages