DLLからの返り値を取得するには

解決


DIC  2005-05-10 12:07:48  No: 14704

いつもお世話になっています。
早速なのですが、CorVC(実はよくわからない)で作成されたアプリから
Delphiで作ったDLLを呼び出し、DLLからの返り値が取得できなくて困っています。

extern "C" __declspec(dllexport)
  void Function(const char* Input, char* Output);
形式で宣言された DLL内の関数を呼び出すものです。
関数呼び出しのときに, Inputに入力文字列が渡されます。
返り値はOutputのバッファに書き込めます。

これに対して私が書いたソースです
function delhoge(input:string):pwidechar;stdcall;
var
    tmp,tmp2,tmp3:string;
begin
//処理の部分は省略

    tmp := '[hoge]' + tmp2 + '  [hoge]' + tmp3;
    result := SysAllocStringByteLen(PCHAR(tmp), Length(tmp));
end;
exports delhoge;

どなたか分かる方いらっしゃいましたら教えて下さい。宜しくお願い致します。


kkk  2005-05-10 12:47:24  No: 14705

VC等からでは 引数に stringは使用できません。
PChar等を使用してください。


kkk  2005-05-10 12:56:06  No: 14706

よく見たら
C側とDelphi側の関数定義の整合性がとれていませんよ。


DIC  2005-05-10 13:17:46  No: 14707

返信有難う御座います。
DLLに渡されたデータをstringで取らずにPCharで取得しろという事ですか?
アプリ側のCで書かれた定義ですが実はよくわかってません。
単にDLLに入力文字列が渡ってきてresultで返せばいいだけなのだと思っていました。
色々調べながらやってみます。


kkk  2005-05-10 13:24:26  No: 14708

>DLLに渡されたデータをstringで取らずにPCharで取得しろという事ですか?
そうです Delphiのstringはメモリの管理方法が異なるのでそのままでは VCやVBとやり取りすることは出来ません。
>単にDLLに入力文字列が渡ってきてresultで返せばいいだけなのだと思っていました。
それならC側では(Delph側にあわせるなら)
void Function(const char* Input, char* Output);
ではなくて
char *Function(const char* Input);
ではないでしょうか?


kkk  2005-05-10 13:29:16  No: 14709

追伸
Delphi側をC側にあわせるなら
procedure delhoge(Input: PChar; Output: PChar); stdcall;
になります。
この定義の場合
Outputのバッファは前もってC側で確保されている必要があります。


DIC  2005-05-10 13:39:35  No: 14710

>char *Function(const char* Input);
>ではないでしょうか?
その通りだと思います。実際DLL側に渡ってきている引数は1つだけで
Outputにあたる部分をdelphi側でどうすればいいのかわからずにいます。

void Function(const char* Input, char* Output);
をdelphiで現すと
Function(const Input,Output:PChar):PChar;
となると思うのですがこの場合返り値を入れる器を用意してくれていると解釈するのですか?


DIC  2005-05-10 13:49:10  No: 14711

上の書き込みの半分より下は見なかった事にして下さいorz

質問ばかりで申し訳ありません。合わせてタイトルとは趣旨の違う質問ばかりでごめんなさい。
C側のアプリのヘルプではバッファは用意してあるような事が書いてあります。
この場合、DLL側からはどのようにして返してあげれば良いのでしょうか?
resultを使うと新たに領域を作って返してしまう形になってしまうような気がするのですが。


kkk  2005-05-10 13:51:35  No: 14712

>void Function(const char* Input, char* Output);
>をdelphiで現すと
>Function(const Input,Output:PChar):PChar;
>となると思うのですがこの場合返り値を入れる器を用意してくれていると解釈するのですか?
いいえ
>Function(const Input,Output:PChar):PChar;
ではなくて
procedure hoge(const Input: PChar; Output:PChar);
ですね。
C側が char *Function(const char* Input);
なら
Delphi側は function hoge(Input:PChar): PChar; stdcall;
となります。


kkk  2005-05-10 13:57:37  No: 14713

C側での正式な定義を教えていただけませんか?


DIC  2005-05-10 14:06:13  No: 14714

LimeChatのヘルプの一部です。
転載は許可されてるみたいなので必要ない部分を消してそのまま載せます。

extern "C" __declspec(dllexport)
  void Function(const char* Input, char* Output);

形式で宣言された DLL内の関数を呼び出すものです. 
Inputに入力文字列が渡されます. 
返値は Outputのバッファに書き込めます. 
渡されるバッファは 1024バイトまでの文字列を保持できます.つまり,nulターミネータを入れて,1025バイトのバッファを用意しています. 

具体的には次のように使います. 

$DllString(mydll.dll,Omikuji,大凶)
>上はlimechatでdllを呼び出すためのマクロです$dllstring(ファイル名、関数名、入力文字列
void Omikuji(const char* Input, char* Output)
{
  if (lstrcmp(Input, "大凶") == 0) {
    lstrcpy(Output, "人生,金だけが頼りです.");
  } else if (lstrcmp(Input, "凶") == 0) {
    lstrcpy(Output, "捨てる神あれば拾う神あり.");
  } else {
    lstrcpy(Output, "人並み以上.");
  }
}
以上です。宜しくお願い致します。


kkk  2005-05-10 14:22:33  No: 14715

単純に
procedure Omikuji(const Input: PChar; Output: PChar); stdcall;
begin
  if StrComp(Input, '大凶') = 0 then
    StrCopy(Output, '人生,金だけが頼りです.')
  else if StrComp(Input, '凶') = 0 then
    StrCopy(Output, '捨てる神あれば拾う神あり.')
  else
    StrCopy(Output, "人並み以上.");
end;
ではどうしょうか?


kkk  2005-05-10 14:29:12  No: 14716

>> StrCopy(Output, "人並み以上.");
SingleQuoteの間違い。ううっ・・・人並み以上にはなれなかった


kkk  2005-05-10 14:38:16  No: 14717

追伸
C側で stdcall が指定されていない場合は
delphi側では cdecl としてください。
procedure Omikuji(const Input: PChar; Output: PChar); cdecl;


DIC  2005-05-10 14:50:56  No: 14718

すごい!思うように処理する事ができました!
呼び出し規約はすみません、適当に付けてましたorz勉強してみます。
procedure Omikuji(const Input: PChar; Output: PChar); cdecl;
begin
  if StrComp(Input, '大凶') = 0 then
    StrCopy(Output, '人生,金だけが頼りです.')
  else if StrComp(Input, '凶') = 0 then
    StrCopy(Output, '捨てる神あれば拾う神あり.')
  else
    StrCopy(Output, '人並み以上.');
end;
で上手くLimeChatへ帰ってきました。
返り値という考え方ではなくC側で用意してくれた場所へデータを載せる。
という考え方に近いのでしょうか。ものすごく勉強になりました。
こんな早朝に長くお時間を使わせてしまって本当に申し訳ありません。OTL
おかげで思うような物が作れそうです。
有難う御座いました!


DIC  2005-05-10 14:51:36  No: 14719

解決にチェックつけるの忘れてた


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

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






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