- PR -

VC++からのクラスアドレスをC#で利用したい

1
投稿者投稿内容
ino
会議室デビュー日: 2004/05/11
投稿数: 13
投稿日時: 2004-05-27 10:34
こんにちは。

VC++6.0で作られたEXEから、あるクラスのアドレスがlong型で送られてきて、
それをocxで受け取り、キャストしてクラスを利用しているアプリケーションがあるのですが、
同じようにクラスのアドレスをC#でも利用したいのですが、受け取ったlong型をキャストして、使おうと思ってもうまくいきません。

現在は、ocxで、
BOOL CDirectEditorCtrl::InitCtrl(long ParentWnd, long MainAppInterfacePtr, LPCTSTR Language, short Unit, short AngleUnit, LPCTSTR VersionInfo)

このようなメソッドを用意して、EXEから2番目の引数でクラスのアドレスを受け取って、

m_pObjectInterfaceProvider = ( IObjectInterfaceProvider* ) MainAppInterfacePtr;
m_pObjectInterfaceProvider->GetObjectInterface( ObjectName, (long**)&pInterfacePointer, &ErrorCode );

上記のように引数をキャストして利用しています。

この2番目の引数をC#で受け取って、同じように利用したいのですが、
キャストがうまくいきません。

C#はクラスメンバにはポインタを宣言できて、クラス自体には宣言できないとなっているのですが、
そのせいでしょうか?

C#で、引数に指定されているアドレスのクラスを利用したいのですが、
なにか方法をご存知の方教えていただけないでしょうか?
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2004-05-27 16:35
引用:

VC++6.0で作られたEXEから、あるクラスのアドレスがlong型で送られてきて、
それをocxで受け取り、キャストしてクラスを利用しているアプリケーションがあるのですが、
同じようにクラスのアドレスをC#でも利用したいのですが、受け取ったlong型をキャストして、使おうと思ってもうまくいきません。



本当にクラスインスタンスのポインタなんですか?
インターフェースポインタだったりしませんか?

どっちであるかで方法は大きく異なります。

引用:

C#はクラスメンバにはポインタを宣言できて、クラス自体には宣言できないとなっているのですが、
そのせいでしょうか?



ズレてるけど、まぁそんな感じですかね。
C++ のクラスと C# のクラスはまったく別物なので、同じように扱うことは出来ません。

あなたが「クラスのアドレス」と呼んでいるものがインターフェースポインタであれば、.NET の COM 連携機能を介して(対象を)操作することが出来ます。

また、本当にそれが「C++ クラスインスタンスのポインタ」であった場合、C# から C++ クラスインスタンスのメンバ関数を呼び出すサンプルが SDK のサンプルフォルダ配下にあるので参考にしてみてください。

あと、同系統の質問が続いているようなので、一度 COM と .NET の COM 連携機能について、書籍などできちんと勉強されることをお勧めしておきます。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
ino
会議室デビュー日: 2004/05/11
投稿数: 13
投稿日時: 2004-05-27 18:43
返信ありがとうございます。


引用: --------------------------------------------

本当にクラスインスタンスのポインタなんですか?
インターフェースポインタだったりしませんか?

----------------------------------------------------


ポインタにはCOMインターフェースのアドレスが入っています。



引用: ------------------------------------------------------------------------

あなたが「クラスのアドレス」と呼んでいるものがインターフェースポインタであれ
ば、.NET の COM 連携機能を介して(対象を)操作することが出来ます。
------------------------------------------------------------------------


申し訳ないのですが、COM連携機能を介してというのは、具体的にどのような方法でしょうか?

参照設定にCOMを追加して、newで作成する方法だと、新しくインスタンスを作るのでポインタで指定された対象を操作できないとおもうのですが。

どうすれば、ポインタで指定されている領域を操作できるのでしょうか?
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2004-05-27 21:52
引用:

申し訳ないのですが、COM連携機能を介してというのは、具体的にどのような方法でしょうか?



そもそもインターフェースポインタを long なんかで受け取るからややこしいことになるのです。

.exe サーバからインターフェースポインタを受け取るメソッドの定義は、C# の場合

void SetHoge(out object pHoge);

のような形式であるべきです。

これは IDL で書くと

HRESULT SetHoge([out] IUnknown** ppHoge);

あるいは

HRESULT SetHoge([out] IDispatch** ppHoge);

に相当します。

ただし、プロセス境界を越えてインターフェースポインタが渡される場合、きちんとマーシャリングしないとまともな動作は期待できませんので念のため。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2004-05-27 21:57
引用:

.exe サーバからインターフェースポインタを受け取るメソッドの定義は、C# の場合

コード:
void SetHoge(out object pHoge);



のような形式であるべきです。



↑の時、タイプライブラリを参照設定して作成されたラッパクラスが HogeClass であれば、

コード:
void SetHoge(out object pHoge)
{
  HogeClass hoge = (HogeClass)pHoge;

  hoge.DoSomeThing();
}



のように、.exe から渡されたインターフェースのメソッドが呼び出せます。

COM の QueryInterface() が C# ではキャスト操作で表現されることは、ヘルプでも解説されています。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
ino
会議室デビュー日: 2004/05/11
投稿数: 13
投稿日時: 2004-05-28 15:41
引用: --------------------------------------------------------------------------

そもそもインターフェースポインタを long なんかで受け取るからややこしいことになるのです。


--------------------------------------------------------------------------------


VC++で作られた既存の.exeを、C#で利用しようとしているので、
インターフェースポインタをlongで渡している部分の変更ができません。


引用:--------------------------------------------------------------------------

void SetHoge(out object pHoge)
{
HogeClass hoge = (HogeClass)pHoge;

hoge.DoSomeThing();
}


--------------------------------------------------------------------------------


上記のようなコードで書くというのは、.exeサーバで渡す部分をVARIANT型などに変更するということですか?

.exeの方は変更できないので、long型で送られてくるのをどうにかして利用したいのですが方法はないのでしょうか?





渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2004-05-28 17:03
引用:

VC++で作られた既存の.exeを、C#で利用しようとしているので、
インターフェースポインタをlongで渡している部分の変更ができません。



そんな変更は必要ありません。

引用:

.exeの方は変更できないので、long型で送られてくるのをどうにかして利用したいのですが方法はないのでしょうか?



前のコメントでそれを説明したつもりです。

インターフェースポインタも long 値も、メモリ上の表現は 4byte 整数です。

.exe 側が long のつもりで渡している情報を、受け側でインターフェースポインタとして受け取ればいいだけの話です。

exe がいじれないってことは、C# で作ったコンポーネントのTLB を exe に与えるわけじゃないんですよね?

であれば、IID とメソッドの並び順さえ同じなら、exe 側が

HRESULT SetHoge(long pHoge);

として呼び出しているメソッドを、C# 側で

void SetHoge(object pHoge);

と実装しても、帳尻は合うのです。

かなり汚いコードですが、元々の exe 側の仕様が出鱈目に近いことをやってるので仕方ないです。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
1

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