DLL、ならびにPChar初心者です。
EXE側から長い文字列を渡し、編集して返すというDLLを作りたいのですが、
バグらないためのDLL側での作法が分かりません。
(1)DLLの引数、戻り値はどのようにすべきでしょうか?
(2)EXE側で、String型をDLLの引数に渡すにはどうすればよいでしょうか?
(3)DLL側での文字列編集は、元の文字長よりも長い結果を返します。
EXE側へはどのように渡せばよいでしょうか?
DLL丸ごと質問みたいで申し訳ありませんが、Webを探してもなかなかズバリの
例に当たりません。よろしくお願いします。
あまり詳しいわけではありませんし、やった事が無いので。
Delphiの開発環境でしか使用しないのなら。
ShareMemユニットをそれぞれのUses節に追加し、
BorlandMM.dllファイルを配布する。
すると、String型でも受け渡しOKです。
簡単になるかな。
dll作成やその際のPChar型変換方法などなど、
「Delphi6 プログラミングバイブル」インプレス
に詳しく掲載されています。
後の参考にもなりますので、購入されては・・・
引数でPCHAR渡しにします。
呼出では、PCHAR(strBuf)などとすればOKです。
例えば
function FuncTest(InStr: PCHAR; OutStr: PCHAR; Len: Integer): Integer; stdcall;
var
strBuf: String;
begin
strBuf := String(InStr); // 引数で渡されたPCHARをStringに変換
{ strBufを加工 }
if (OutStr <> nil) and (Len > Length(strBuf) then
begin
CopyMemory(OutStr, PCHAR(strBuf), Length(strBuf)+1);
end;
Result := Length(strBuf)+1;
end;
というようにして、呼出で
l := FuncTest(PCHAR(InStr), nil, 0);
SetLength(OutStr, l - 1);
FuncTest(PCHAR(InStr), PCHAR(OutStr), l);
もしくは、
l := FuncTest(PCHAR(InStr), nil, 0);
OutBuf := SysGetMem(l);
FuncTest(PCHAR(InStr), OutBuf, l);
OutStr := String(OutBuf);
SysFreeMem(OutBuf);
とします。
戻り値の場合は、DLL内部でAllocateし、呼出側で破棄する必要があります。
その場合は、SysGetMem,SysFreeMemでなく、APIで確保する必要があります。
# DLL内部でのメモリマネージャと、呼出側のメモリマネージャが違うため
ご回答ありがとうございます。
Syake様、今回は勉強のためShareMem非使用にこだわりましたのでごめんなさい。
書籍情報については参考にさせていただきたいと思います。
にしの様、色々と参考になりました。内容は理解できます。
まずはこれを基本に組んでみようと思います。
ただ、編集作業自体が結構大きいため、長さ限定用と実行用に二度呼び出す
というのに少々抵抗があるのですが、最初から十分な量のメモリを確保しておいて、
そこに渡すなんてことはできないでしょうか?
すみません、何分安易なString型以外の分野について知識が薄いもので……。
最大文字列長分のバッファを確保しておけば問題ないですよ。
その後自分なりにも色々と試してみましたが、うまくいきませんでした。
メモリを直接扱うにはまだまだ基礎力不足かなぁ、
などとも感じたりしております。
PChar関連の関数等の一覧がヘルプにありますが、似たのが多くて混乱します。
せっかくご協力いただけたのに申し訳ありません。
厳密には解決ではありませんが、ここは一旦閉じさせていただいて、
PCharを一から勉強し直します。ありがとうございました。
解決チェック忘れ
にしのさんのコードは例としてとてもいいものだと思います。
どのようなコードを書いてどのようにうまくいかなかったのかを書かないと
にしのさんの努力が無駄になりそうで残念です。
これ以上お聞きするのも恐縮に思いました。
にしのさんのコードは、たとえばSysGetMem()とかCopyMemory()とか、
それまで全く知らなかったことをお教えいただき感謝しております。
ツイート | ![]() |