- PR -

DLL同士の通信

投稿者投稿内容
優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-09 13:07
ほむらさん、Jittaさん、
ありがとうございます。


引用:

ほむらさんの書き込み (2004-02-09 10:09) より:

とりあえず、手近なところからということで
DLLがいけないのかソースコードの記述がいけないのかを確かめる上でも
DLLじゃなくて1個のプログラムとしてマージしてみるとか。。。
box化したときに手に入るのはコピーみたいですし。。。

ひとつのプログラムにしたときに同じエラーならソースの違い
うまくいった場合はDLL経由というのが悪さしているということでどうでしょう?
#できれば前者であってほしいものですね^^;;;;



これって、
自分が書き込んで(投稿日時: 2004-02-06 09:43 )、
やってみたこととは違うのでしょうか?
もう少し深入りした・・・ってことかな(−−;)

引用:

ちなみに、
送信側↓でBOX化したあとに、
すぐにBOX化解除してメッセージボックスに出したら、
きちんと表示されたんですよねぇ(^^;)

コード:

SendDataTbl param;             // 構造体
ArrayList *lstSendData = new ArrayList(); // リスト格納用

// データ格納(仮に3つ)
param.str1 = TextBox1->Text; // String型
param.str2 = Label1->Text; // String型
param.str3 = strVersion; // String型

// 設定
Object* ptrPrm = __box(param); // Object型にボックス化
lstSendData->Add(ptrPrm); // ArrayListに設定

// ◆◆試しに追加◆◆
SendDataTbl recieveData =
*dynamic_cast<__box SendDataTbl*>(lstSendData->get_Item(0));
MessageBox::Show(recieveData.str1);







続いて、こちらですが、
引用:

Jittaさんの書き込み (2004-02-09 10:22) より:

 そですね。
それと、気になるのが、私のサンプルではそうしたのですが、実行形1個にライブラリ2個ですよね。で、ライブラリ間で値を受け渡ししたいと。ここで優希さんのPGの全体が見えないのですが、今エラーがでているのは「渡されたライブラリ」ですよね。この「渡す」操作を、
・ライブラリ間で直にやっているのか
・実行形が親として中継しているのか
というところ。で、中継しているなら、中継現場ではどのようになっているのか。



今、自分でやっているのでは、

ライブラリ1 ⇒ IWrapDll(インタフェース)⇒ ライブラリ2

となっています。
なので、『実行形が親として中継しているのか 』というわけではないと思います。

コード:

String *strDllName = S".\\lib1.dll";// DLL名称
String *strClsName = S"Namespace1,Cls";// クラス名称

// アセンブリの読み込み
Assembly *asmb = Assembly::LoadFrom(strDllName);

// インスタンスの生成
IWrapDll *wrapInst = dynamic_cast<IWrapDll*>(asmb->CreateInstance(strClsName));

if(wrapInst != 0){
wrapInst->ReceiveData(picChild); // データ送信
}




それと、
引用:

Jittaさんの書き込み (2004-02-09 10:22) より:

 そして、「直にやりたい」ということですが、
「直にやる」為には親が子に、もう一人の「子」を教えてやらなければならないのですが、その「子を教える」ところがどうなっているのか。また、型の情報をそれぞれのライブラリは知っているのか。ま、知っていなければコンパイル時にエラーがでているでしょうけど(^^;



とのことですが、
今は試験的に・・・
(ライブラリが2つ以上あるので時間を要する為、
 この問題が終わってからやるつもりですが(^^;))
ソースの中で固定で送信先のDLL名称やらを記述しております。

今、そこで悩んでいまして、送信先になりうる
全てのライブラリの情報を渡してやる必要があるなって
考えております。



引用:

#####
えっと、ちょっと気になっていたのでこの辺で書いておきます。
    :
   省略
    :


そうですねぇ、
結構、長い問題になってきていますねぇ(^^;)

やはり、いろいろアドバイスを頂けると、
こちらも励みになりますし、やる気も沸いてきます。

質問者としては、
できる範囲では自分でやってみて納得したいですからね。


[ メッセージ編集済み 編集者: 優希 編集日時 2004-02-09 13:09 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-09 14:02
引用:

優希さんの書き込み (2004-02-09 13:07) より:

ライブラリ1 ⇒ IWrapDll(インタフェース)⇒ ライブラリ2

となっています。
なので、『実行形が親として中継しているのか 』というわけではないと思います。


 インタフェースでなく、Abstract Classにする…関係ないか。「イベントを実装していない」というのは、そういう意味だったのですね。アセンブリのロードを、誰がやっているのか、気になってました。

 DLLを「プロジェクト参照」していると、きっと通るんだろうな。メモリ参照で渡されているはずなので、それが通らないのか?それともインタフェースにキャストしているのがダメなのか?インスタンスを「インタフェース」ではなく「クラス」にキャストすると、どうなりますか?
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-02-09 14:17
ども、ほむらです。
------
優希氏へ
引用:

これって、
自分が書き込んで(投稿日時: 2004-02-06 09:43 )、
やってみたこととは違うのでしょうか?
もう少し深入りした・・・ってことかな(−−;)


このやり方だと、同じ関数の中で使っていてるので
できて当然という考えがあります。

たぶん、引数の渡し方に問題はないと思うのであと怪しいのは
アプリケーションドメインなるものに引っかかっていないか検証したいのです。
DLL(.NETではアセンブリというのですか?)が別々のものだとすると
アドレスが制限に引っかかってしまっているんじゃないかなと。。。

で、なのでDLLを使わずに一つのEXE形式としてやってみた場合はどうなんでしょうと。
やり方としては、IWrapDll そのものを取り込めれば最高なのですけど
なんか無理っぽいですしとりあえずReciveData()だけ取り込んでみる形でもいいかなと

これで、データの作成と受け渡しに格納上のエラーがないかはわかると思います。

このやり方で引っかからなかったらあとは。。。仕様ですか?(笑

#ちなみに、アプリケーションドメインに引っかかっているようですね^^;;;;
#よくわからないけど、
#.NET アプリケーションドメイン間通信
#で検索してみたらリモーティングなる技術が必要らしい記述をみかけました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-09 14:47
引用:

ほむらさんの書き込み (2004-02-09 14:17) より:

たぶん、引数の渡し方に問題はないと思うのであと怪しいのは
アプリケーションドメインなるものに引っかかっていないか検証したいのです。
DLL(.NETではアセンブリというのですか?)が別々のものだとすると
アドレスが制限に引っかかってしまっているんじゃないかなと。。。


 それは私も疑いました。が、もしそうだと、複数プロジェクトというのが全て引っかかりませんか?もっともこの場合、DLLを読み込んで、インスタンスCreateInstanceで作っているので、それでアプリケーションドメインが別になっている可能性はあります。が、そうするとArrayListそのものも渡せないのではないかと。。。

引用:

#よくわからないけど、
#.NET アプリケーションドメイン間通信
#で検索してみたらリモーティングなる技術が必要らしい記述をみかけました。


 .NET F/Wに、標準で用意されているのはTCP/IPとHTTPなんですね。「アプリケーションドメイン」が「別コンピュータに構築」されているのが前提なのか?と疑ってしまう(^^;。「標準」を利用しようとすると、TCPのポートを開かないといけないので、そうやってセキュリティーホールのもとを作り込むのも何かと思い、サンプルを作るのを止めました。
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-02-09 15:18
的はずれだったら申し訳ないのですが
もしかしてSendDataTbl構造体を両方のDLLで定義してませんか?

それだとDLL1のSendDataTbl構造体とDLL2のSendDataTbl構造体は
別なものと認識されませんかね

それでDLL1でBOXしたのをDLL2で元に戻せない(型が違うので)

ためしにSendDataTbl構造体のかわりにCStringをBOXしてためしてみたらどうなります?



[ メッセージ編集済み 編集者: ゆうじゅん 編集日時 2004-02-09 15:20 ]
優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-09 15:35
Jittaさん、ほむらさん、
有難う御座います。

引用:

Jittaさんの書き込み (2004-02-09 14:02) より:

DLLを「プロジェクト参照」していると、きっと通るんだろうな。メモリ参照で渡されているはずなので、それが通らないのか?それともインタフェースにキャストしているのがダメなのか?インスタンスを「インタフェース」ではなく「クラス」にキャストすると、どうなりますか?



これは、現在↓の

ライブラリ1 ⇒ IWrapDll(インタフェース)⇒ ライブラリ2

を、↓にするってことですね!?

ライブラリ1 ⇒ ライブラリ2


まず、送信側で以下のようにやります。
コード:
///
/// 送信側ソース
///

// 受信側のDLL参照
#using <ReceiveCls.dll>
    :
    :

// データ送信関数
void SendOwnData()
{
    // データ取得
       :
       :

    // アセンブリの読み込み
    Assembly *asmb = Assembly::LoadFrom(strDllName);
    // インスタンスの生成
    ReceiveCls *wrapInst = dynamic_cast<ReceiveCls*>(asmb->CreateInstance(strClsName));

    if(wrapInst != 0){
	wrapInst->ReceiveData(lstSendData);		// データ送信
    }
}



すると、今度はエラーにならず、
受信側できちんと値も取得できました(^^)v



そして、
ほむらさんの書込みについてですが、

引用:

ほむらさんの書き込み (2004-02-09 14:17) より:

で、なのでDLLを使わずに一つのEXE形式としてやってみた場合はどうなんでしょうと。
やり方としては、IWrapDll そのものを取り込めれば最高なのですけど
なんか無理っぽいですしとりあえずReciveData()だけ取り込んでみる形でもいいかなと



これは、
ReciveData()関数を送信側のソースに移しテストするってことでしょうか?

コード:
///
/// 送信側ソース
///

 :
 :

// データ送信関数
void SendOwnData()
{
    // データ取得
    :
    :

	// ★追加★
	// 自ソースの関数呼び出し
	ReceiveData(lstSendData);

	// ★コメント★
	// アセンブリの読み込み
	//Assembly *asmb = Assembly::LoadFrom(strDllName);
	// インスタンスの生成
	//IWrapDll *wrapInst = dynamic_cast<IWrapDll*>(asmb->CreateInstance(strClsName));
	//if(wrapInst != 0){
	//	wrapInst->ReceiveData(lstSendData);		// データ送信
	//}
}

// ★追加★
// データ受信関数(送信がわに移行)
void ReceiveData(ArrayList *DataTbl)
{
	Object *obj = DataTbl->get_Item(0);
	SendDataTbl pData = *dynamic_cast<__box SendDataTbl*>(obj);

	MessageBox::Show(pData.Str);
}




上記のソースを試すと、
きちんと値は取得できます。


・・・ということは、
インタフェースを間に入れると
何らかの影響で受け取り不可になるんですかねー(^^;)


続いて、
ゆうじゅんさんの書込みですが、
引用:

もしかしてSendDataTbl構造体を両方のDLLで定義してませんか?


もしかしたら、両方で定義していたかもしれません。
ちょっと確認してみます。



ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2004-02-09 15:47
ほむらです。
--------
Jitta氏へ
引用:

 それは私も疑いました。が、
もしそうだと、複数プロジェクトというのが全て引っかかりませんか?
もっともこの場合、DLLを読み込んで、インスタンスCreateInstanceで作っているので、
それでアプリケーションドメインが別になっている可能性はあります。が、
そうするとArrayListそのものも渡せないのではないかと。。。


#改行位置変更しましたm(__)m
書き込んだ後、読み進めていったらAssembly::LoadFromは
自分と同じアプリケーションドメイン内にアセンブリを読み込むみたいですね。
アプリケーションドメインの問題じゃないとなるとなんですかね〜。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2004-02-09 16:02
普通にDLLやらアセンブリを使用していて、いつの間にか違うアプリケーションドメインになっているなどということはありえません。

スキルアップ/キャリアアップ(JOB@IT)