DOBON.NET DOBON.NETプログラミング掲示板過去ログ

exe⇔dll間の構造体の受け渡し

環境/言語:[XP VB.NET Framework2.0]
分類:[.NET]

最近このサイトを知り、参考・利用させてもらっています。
VB.NET4日目の初心者です。

実現したいことなんですが、
入力フォーム(exe)で入力されたキー情報を構造体に設定し、
その構造体のキー情報を検索フォーム(dll)上に設定します。
検索後、検索結果の中から選択された1行のデータを同じ構造体に設定し、
入力フォーム側に返します。
つまり、1つの構造体でキー情報(in)、検索結果(out)を管理させ、
それをexe⇔dll間で使うということです。

構造体の定義の仕方は調べてやっとわかってきたのですが、
その構造体の受け渡し方がわからず手が止まってしましました。

どなたかアドバイス、参考サイトなど教えていただければ幸いです。
どうぞよろしくお願いします。
■No16545に返信(トップ姫さんの記事)
> 構造体の定義の仕方は調べてやっとわかってきたのですが、
> その構造体の受け渡し方がわからず手が止まってしましました。
引数で渡せばいいんじゃないでしょうか。
その検索フォームにPublicなメソッドを追加して引数で渡す。
結果は戻り値で返すなんてどうです?

Public Function SearchHoge(ByVal item As StructItem) As StructItem
  If Me.ShowDialog() = DialogResult.OK Then
    Dim returnValue As StructItem
    returnValue.Result1 = Me.txtResult1.Text
    returnValue.Result2 = Me.txtResult2.Text
      :
    Return returnValue
  End If
End Function

'確定ボタンだとする
Private Sub AcceptButton_Click()
  Me.DialogResult = DialogResult.OK
End Sub
はいこーんさんがとても丁寧にコード付きでお書きになられてるので
もういいかとも思いますが…

Integerの値だろうが自分で作ったクラスや構造体の値(インスタンス)だろうが、
同様に受け渡しできますよ。
#本題の目的とは別のお話です

> Public Function SearchHoge(ByVal item As StructItem) As StructItem

値型(Structure)なので別物になっちゃうのではないですかね?

>   If Me.ShowDialog() = DialogResult.OK Then

Me.ShowDialogってよく使うんでしょうか(^^;
たしかにフォームリソースを表示っていうのは独立したアクション、
でも、その呼び出しも含めてすべてClass〜End Class内にある。
うーん、なんか混乱してます。。。

クラスでインスタンスをやり取りしたほうがいいと思うんだけど、アセンブリ間ではどうなんだろう?
http://msdn2.microsoft.com/ja-jp/library/ms229017.aspx
■No16551に返信(まどかさんの記事)
> 値型(Structure)なので別物になっちゃうのではないですかね?

問題あるのでしょうか?
私の感覚ですと、構造体を選択している時点で、"問題がないと判断しているから" がしかりだと思っています。

# 質問を見る値、戻り値としてではなく、引数でそのまま結果を受け取ろうとしているように見えますけどね...
# 戻り値で受け取った方が、良い設計でしょうね。

> Me.ShowDialogってよく使うんでしょうか(^^;

検索 Form では、この方がわかりやすい場合はありますね。(サービス志向といいますか)
何がわかりやすいかといいますと、その公開メソッドの戻り値にだけ着目できるという点です。
外から見た場合、Me.ShowDialog の存在なんて関係ないですし。

それ以外の正当な方法は、外で ShowDialog メソッドを呼び出し戻り値を確認。
DialogResult.OK だったら、専用の Result プロパティから、結果を取得のような流れでしょうか。

> たしかにフォームリソースを表示っていうのは独立したアクション、
> でも、その呼び出しも含めてすべてClass〜End Class内にある。
> うーん、なんか混乱してます。。。

これについては意味がわかりませんでした。

> クラスでインスタンスをやり取りしたほうがいいと思うんだけど、アセンブリ間ではどうなんだろう?
> http://msdn2.microsoft.com/ja-jp/library/ms229017.aspx

ここで最初の 1 行目の話題になっていますね。
唐突に戻ってしまったので、どちらの話なのかちょっとメダパりましたw

別物になっても問題ない設計だから、構造体にしているんじゃないですかね。
私の場合、検索フォームは複数件返すこともあるので、たいていがコレクションになります。
その観点で見れば、違和感はあるのですが、サンプルコードとしては、全然問題ないと思います。
質問者が所望してきたのが構造体なのですから、という理由でしかありませんけど。
みなさん、お返事本当にありがとうございます。

はいこーん さん丁寧なサンプルソースありがとうございます。
参考にさせていただき組み込んだところデータの受け渡しがうまくできました。
感謝ですm(__)m

こど。さんコメントありがとうございます。また助けていただきましたね。

まどか さん参考URL拝見しました。「インスタンスのサイズが 16 バイト未満であること」とありました。わたしの作った構造体はテーブルの1レコード分のデータなので16バイトは余裕で超えてしまいます。クラスの方が良い設計ということになるのかな???

じゃんぬねっと さんのお察しの通り考えていましたが、アドバイスいただいた戻り値で受け取るようにしました。
> # 質問を見る値、戻り値としてではなく、引数でそのまま結果を受け取ろうとし> ているように見えますけどね...
> # 戻り値で受け取った方が、良い設計でしょうね。
(余談ですが、あの憧れのじゃんぬねっとさんからコメントいただけて、うれしいです♪@^^@ウハ)
解決済み!
■No16555に返信(トップ姫さんの記事)
> まどか さん参考URL拝見しました。「インスタンスのサイズが 16 バイト未満であること」とありました。
> わたしの作った構造体はテーブルの1レコード分のデータなので16バイトは余裕で超えてしまいます。
> クラスの方が良い設計ということになるのかな???

はい、そうなると思います。
(一般的には構造体を選択する場面の方が格段に少ないです)

しかし、そこ以上に重視したいのは、構造体のメンバが単純であるかどうかです。
また、複数件の結果を返すようであれば、間違いなくクラスというかコレクションを返した方が良いです。

> じゃんぬねっと さんのお察しの通り考えていましたが、アドバイスいただいた戻り値で受け取るようにしました。

はい、参照渡しは直感的ではないのと、コード変更時に危険をはらみますから、
戻り値として '敢えて' 「別の入れ物」 で返した方が良いです。

しかし、引数に渡す情報と戻ってくる情報が同じ型であるというのは違和感があります。
これは勝手な想像なんですが、渡したい情報と取得したい情報が一緒になっていませんか..?

> (余談ですが、あの憧れのじゃんぬねっとさんからコメントいただけて、うれしいです♪@^^@ウハ)

そう言って頂けると、私も嬉しいです。
皆さまには、いつもお世話になっております。(*__ __)
解決済み!
じゃんぬねっと さん返信ありがとうございます。

#管理人さん、みんさん、解決済みなのに続けててすみません。

> しかし、そこ以上に重視したいのは、構造体のメンバが単純であるかどうかです。
> また、複数件の結果を返すようであれば、間違いなくクラスというかコレクションを返した方が良いです。
> 
> はい、参照渡しは直感的ではないのと、コード変更時に危険をはらみますから、
> 戻り値として '敢えて' 「別の入れ物」 で返した方が良いです。
> 
> しかし、引数に渡す情報と戻ってくる情報が同じ型であるというのは違和感があります。
> これは勝手な想像なんですが、渡したい情報と取得したい情報が一緒になっていませんか..?

下記のような構造体をdll側に宣言しています。
検索フォームから返すのは1件だけです。
入力フォーム側からKey1〜3を設定し、検索フォームでそれを条件にして
検索した結果をcolumnA〜Dに入れて入力フォームに返します。
(key3は検索フォーム側で入力し直すこともできるためI/Oになっています)
これは、まさしくじゃんぬねっと さんが懸念されているよう”一緒”という
ケースになるのでしょうか?

    Public Structure 構造体A
        Public key1 As String        '[I]  キー1
        Public key2 As String        '[I]  キー2
        Public key3 As String        '[I/O]キー3
        Public columnA As String     '[O]  取得項目A
        Public columnB As integer    '[O]  取得項目B
        Public columnC As integer    '[O]  取得項目C
        Public columnD As String     '[O]  取得項目D
    End Structure
ゴメンなさい。解決済みチェック忘れてました。
解決済み!
>>値型(Structure)なので別物になっちゃうのではないですかね?
>
> # 質問を見る値、戻り値としてではなく、引数でそのまま結果を受け取ろうとしているように見えますけどね...

それが大きな理由でした。

>>Me.ShowDialogってよく使うんでしょうか(^^;
>
> 検索 Form では、この方がわかりやすい場合はありますね。(サービス志向といいますか)
> 何がわかりやすいかといいますと、その公開メソッドの戻り値にだけ着目できるという点です。
> 外から見た場合、Me.ShowDialog の存在なんて関係ないですし。

個人的に公開クラス+Friendフォームなんていう構造が主だったりするので
Me.ShowDialogって書いたことが無かったりします。。。
よく考えれば昔からLoadでMe.Showなんてことをしてるわけで、問題ないですね。
単にぱっと見自分で自分の結果待ちっていうのに反応してしまっただけでした。
解決済み!
■No16565に返信(トップ姫さんの記事)
> #管理人さん、みんさん、解決済みなのに続けててすみません。

受け渡しに関することですから、お許しくださるかと...
気になるようでしたら、別スレッドへ移動します。

> 下記のような構造体をdll側に宣言しています。
> 検索フォームから返すのは1件だけです。
> 入力フォーム側からKey1〜3を設定し、検索フォームでそれを条件にして
> 検索した結果をcolumnA〜Dに入れて入力フォームに返します。
> (key3は検索フォーム側で入力し直すこともできるためI/Oになっています)
> これは、まさしくじゃんぬねっと さんが懸念されているよう”一緒”という
> ケースになるのでしょうか?

はい、そういったケースになります。

受け取る側の都合と受け渡す側の都合だけで考えてみてください。
このメソッドを組んだ方以外は、何をどうすれば良いのか直感ではわかりません。

以下のように受け渡し用と受け取り用と分けるべきだと思います。

    Public Class 受け渡し用
        Public Key1 As String '[I] キー1
        Public Key2 As String '[I] キー2
        Public Key3 As String '[I] キー3
    End Class

    Public Class 受け取り用
        Public Key3    As String  '[O] キー3
        Public ColumnA As String  '[O] 取得項目A
        Public ColumnB As Integer '[O] 取得項目B
        Public ColumnC As Integer '[O] 取得項目C
        Public ColumnD As String  '[O] 取得項目D
    End Class

単純なデータクラスですが、動的なチェックが必要な場合はプロパティを使った方が良いです。
受け取ったものは、勝手に改変されないように ReadOnly 修飾子をつけた方が良いでしょうね。

このあたりは、サンプルなので割愛しています。
解決済み!
■No16568に返信(まどかさんの記事)
> それが大きな理由でした。

フォローを書いておいて良かったです。

> 個人的に公開クラス+Friendフォームなんていう構造が主だったりするので
> Me.ShowDialogって書いたことが無かったりします。。。

あれ? 公開クラス + 隠蔽化されたインナークラスじゃないんですねw

この場合は、
> > それ以外の正当な方法は、外で ShowDialog メソッドを呼び出し戻り値を確認。
> > DialogResult.OK だったら、専用の Result プロパティから、結果を取得のような流れでしょうか。
こんなイメージなのがありがちでしょうね。

ShowDialog メソッドについては場所よりか、タイミングの方が重要だと思います。

> よく考えれば昔からLoadでMe.Showなんてことをしてるわけで、問題ないですね。
> 単にぱっと見自分で自分の結果待ちっていうのに反応してしまっただけでした。

そういう意味では Load イベントのタイミングで Show メソッドを呼び出す方が違和感があります。
Load ステートメントだけで Show メソッドを呼び出してしまうのは実装者からすれば予想外の出来事です。

    Call Load(frmHoge)

究極的には Show~ なんて名前のメソッドであれば、実装者は予想できることになります。
解決済み!
じゃんぬねっとさん、お返事ありがとうございます。

>受け取る側の都合と受け渡す側の都合だけで考えてみてください。
>このメソッドを組んだ方以外は、何をどうすれば良いのか直感ではわかりません。

そうですね。可読性をよくするのはプログラミングの基本ですよね。
.NETでどうやってコーディングすればよいのか?にばかり神経が行ってて
うっかりしていました。(^-^)ゞ

ご忠告ありがとうございます。さっそくこの後見直してみます。
助かりました。v(⌒o⌒)v
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板