WorkToolSmith

char**に悩む

太田アベル

・ 2分で読めます

当サイトの記事には広告リンクが含まれる場合があります。

CからDelphiへの移植は、ポインタの違いに大変悩まされます。

特に悩むのがこの char** などのポインタ記号が二つ付いたもの。

Cの表記には謎が多いです。

それを使っているのはこの命令

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

複数のファイルを1つのDocuworksファイルにするというものです。

たぶんchar**は2次元ということでしょうね。
array of array of pcharみたいな。

まあ配列をポインタで渡せばいいだろうと思い込んで

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

にしてみました。
思いっきり生のポインタです。

var
  f: array[0..1] of pchar;

として

 f[0] := DWファイル
 f[1] := DWファイル2
XDW_MergeXdwFiles(@f, 2, pchar(アウトプットファイル名), xdw_null);

これで成功しました。

しかし、ファイルは2個以上の場合もありえます。

そこで

var
 f: array of pChar;

にして
TStringsなんかでファイルリストを受け取ることにします。

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

で

XDW_MergeXdwFiles(@f, FileList.Count, pchar(アウトプットファイル名), xdw_null);

としてみましたが・・・

ここでエラー発生!!!なぜに~!?

単純なコードなので間違えようがありません。
散々悩んだあげく、またしてもMLのお世話になることにしました(;^^

高木さんからアドバイスをいただけました

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

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

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

な、なるほど~(」゜ロ゜)

つーことは、array of にした変数はその時点でポインタだということですね。

手直し

XDW_MergeXdwFiles(@f[0], FileList.Count, pchar(アウトプットファイル名), xdw_null);

これでまず成功!

そして応用。
fをそのまま渡します。

XDW_MergeXdwFiles(f, FileList.Count, pchar(アウトプットファイル名), xdw_null);

これも成功!

またひとつおりこうになりました。(^_^;

太田アベル

太田アベル

パソコンを7歳からいじり始めて40年。とにかくパソコンが好きです。気になった商品をほぼ自腹で買いまくってレビュー中!良かった点、悪かった点をズバズバ書きます。

𝕏 でフォロー プロフィールを見る

こちらもおすすめ