Watch, Follow, &
Connect with Us

Please visit our new home
community.embarcadero.com.


Welcome, Guest
Guest Settings
Help

Thread: DLLとの文字列の受け渡しがうまくいきません


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 6 - Last Post: Oct 25, 2017 8:02 PM Last Post By: Makoto Saito Threads: [ Previous | Next ]
Hideyuki Oya

Posts: 87
Registered: 6/6/07
DLLとの文字列の受け渡しがうまくいきません  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 12, 2017 10:05 PM
Delphiで作成したプログラムが長くなったため(そして、C#でも使いたいため)、一部をDelphiでDLL化しています。
作成したDLLはC#のプログラムからは正常に(たぶん)動作するのですが、Delphiから使おうとすると(実行すると)エラーになります。(エラーメッセージはaccess violation at 0x00000000)
文字コードが一致していないとも思うのですが、よくわかりません。

動作確認のためShowMessageで表示させています。

//DLLの中身(主要部だけ)

function conv_date(str_address:PWChar;buffsize:Integer):bool;stdcall;
begin
str := string(str_address);

ShowMessage(str_address);//動作確認のため--> 完全に文字化け
ShowMessage(IntToStr(buffsize));//動作確認のため--> 6070170

//処理
...

StrCopy(str_address,PChar(str));
result := true;

end;

//DLL確認プログラム
function conv_date(buff:PWChar;buffsize:Integer):String;external 'RT110.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2.Text := string(conv_date(PWChar('123456'),10));//データおよびbuffsizeは適当 ここでエラー
end;

Hikaru FUKUSHI

Posts: 65
Registered: 11/11/02
Re: DLLとの文字列の受け渡しがうまくいきません  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 13, 2017 12:29 AM   in response to: Hideyuki Oya in response to: Hideyuki Oya
Oyaさん、こんにちは。福士です。

単純に関数の宣言が一致していませんが、これは気のせいですか?

| function conv_date(str_address:PWChar;buffsize:Integer):bool;stdcall;

| function conv_date(buff:PWChar;buffsize:Integer):String;external 'RT110.dll';

# 戻値の型、呼び出し規約が違いますよね?

DLLを作成する場合、まずはテスト用のプログラム内にDLLのエクスポート関数を
そのまま入れてしまって呼び出すようにすると、デバッグなどが簡単ですので
お勧めです(DLLとしては別途デバッグが要りますが)。

--
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fukushi@tts-inc.co.jp

Hideyuki Oya

Posts: 87
Registered: 6/6/07
Re: DLLとの文字列の受け渡しがうまくいきません  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 15, 2017 12:06 AM   in response to: Hikaru FUKUSHI in response to: Hikaru FUKUSHI
福士さん、ありがとうございます。
| function conv_date(str_address:PWChar;buffsize:Integer):bool;stdcall;

| function conv_date(buff:PWChar;buffsize:Integer):String;external 'RT110.dll';

# 戻値の型、呼び出し規約が違いますよね?
そこまでは気が付きませんでした。
C#では(一見?)正常に動いていますので、入力するデータ型が間違っているとばかり思っていました。
(C#の方もまだ作成途中ですけど)

でも他にもあるようです。
デバッグしてみると、StrCopy(sentence_address,PWChar(sentence));のところで
'access violation at 0x00421a2b: write of address 0x005ca0c0'というエラーメッセージが出ています。
以上、途中経過です。

DLLを作成する場合、まずはテスト用のプログラム内にDLLのエクスポート関数を
そのまま入れてしまって呼び出すようにすると、デバッグなどが簡単ですので
お勧めです(DLLとしては別途デバッグが要りますが)。
確かにそうですね。
完璧なDLL化と思ったんですが、余計な処理をしていました。
Hideyuki Oya

Posts: 87
Registered: 6/6/07
Re: DLLとの文字列の受け渡しがうまくいきません  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 15, 2017 10:23 PM   in response to: Hideyuki Oya in response to: Hideyuki Oya
自己レスです。
やっと原因がわかりました。
メモリを確保して渡さないとダメなんですね。
srr0 := 'ABCDE'; だけでメモリ確保してるのかと勘違いしていました。

//呼び出し側
var
pc:PChar;

...
pc := StrAlloc(30);
StrCopy(pc,'ABCDE');
conv_date(pc,30);//DLL呼び出し

Edit2.Text := String(pc);

という感じで正常動作しました。
福士さん、ありがとうございます。
Makoto Saito

Posts: 26
Registered: 12/5/04
Re: DLLとの文字列の受け渡しがうまくいきません  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 16, 2017 8:16 PM   in response to: Hideyuki Oya in response to: Hideyuki Oya
Oya さんのは省略があるので,具体的な詳しい動作仕様は分かりませんが,
単に DLL の関数に文字列を渡すだけなら以下のコードでもできるようです.
Windows 7 U64(SP1) + Delphi XE(UP1) Pro で確認しました.
//----------------- DLLの全コード-----------------------------------------
// ファイル名は DllTest_PChar.dpr
 
library DllTest_PChar;
 
uses
  Windows,
  SysUtils,
  Dialogs;
 
function SetText2Dll(Buff: PChar):Bool; stdcall;
var
  LText : string;
begin
  LText := string(Buff);
  ShowMessage(LText);
  Result := True;
end;
 
exports
  SetText2Dll;
 
end.
 
 
//----------------- テスト側のコード ------------------------------------------
 
implementation
 
{$R *.dfm}
 
function SetText2Dll(Buff: PChar):Bool; stdcall; external 'DllTest_PChar.dll';
 
procedure TForm1.Button1Click(Sender: TObject);
var
  LPChar : PChar;
begin
  LPChar := PChar('ABCDE');
  Edit1.Text := BoolToStr(SetText2Dll(LPChar));
end;
Hideyuki Oya

Posts: 87
Registered: 6/6/07
Re: DLLとの文字列の受け渡しがうまくいきません  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 19, 2017 11:38 PM   in response to: Makoto Saito in response to: Makoto Saito
Makoto Saito さん、回答ありがとうございます。

今回のは、文字列の一部を変換して返すDLLなので、上記のようでないとダメなようです。
他にも方法があるかもしれませんけど。
Makoto Saito

Posts: 26
Registered: 12/5/04
Re: DLLとの文字列の受け渡しがうまくいきません  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 24, 2017 4:08 AM   in response to: Hideyuki Oya in response to: Hideyuki Oya
今回のは、文字列の一部を変換して返すDLLなので、上記のようでないとダメなようです。
他にも方法があるかもしれませんけど。
解決済みになっているのでくどいですが.

もしかして,DLL の関数の文字列引数を入出力兼用として使用しようとしていませんか ?
つまり,DLL に文字列を渡す引数と,DLL から文字列を取得する引数に同じ引数を使おうとしているかです.
もしそうでしたら,別々にした方がよろしいかと思います.
見当違いでしたらご容赦ください.

それから,質問の時には,省略したコードではなく,
実際に他の方がテスト可能なコードにした方がいいと思います.
必要て最小限のコードを提示すべきですね.
そうすればテストする方もいるかも知れません.
テストが面倒だと質問の流し読みだけになってしまいます.

このことは,ネット上のサンプルを自分がやってみようとする時を考えてみるといいと思います.
昔から何回も言い尽くされてきたことですので,今更書くのも恥ずかしいのですが.

参考
[05_文字列変数を DLL の入出力兼用の引数として使用する方法]
http://mrxray.on.coocan.jp/Delphi/plSamples/001_UseDLLProject.htm#05

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02