C#のCOM DLL にコールバックを設定したい – プログラミング – Home

C#のCOM DLL にコールバックを...
 
通知
すべてクリア

[解決済] C#のCOM DLL にコールバックを設定したい


mom
 mom
(@mom)
ゲスト
結合: 9年前
投稿: 17
Topic starter  

非常に悩んでおり、教えてください。

■環境VS2008と作成したプロジェクト

① C#のCOM DLLを作りました

② ①を呼び出すC++ MFCを作りました。

③ ①を呼び出すC# Formを作りました。

■行いたい動作
②もしくは③にコールバック関数を作成し、①へそのコールバック関数を設定する。
①の何かしらのアクション時にコールバック関数を呼び出したい。

お願いします。


引用未解決
トピックタグ
C#
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

うーん、
まず、
1.
>、①へそのコールバック関数を設定する。
これは、DLLを使う以上無理だと思います。

2.
>②もしくは③にコールバック関数を作成し、
設定も②もしくは③で行う。

3.
>①の何かしらのアクション時にコールバック関数を呼び出したい。
Dllとアプリケーションと共通のユ-ザーイベントを作る。
DLLとアプリケーションの間なのでレジストリー登録しないといけないのかな?

です。

あくまで、コールバック関数は、アプリケーション側で作成・実行ですね。

 DLLは、初期化コードを実行することが出来ないので、コールバック関数等は
作成・実行はできないと思います。

WIN32API等で設定されているコールバック関数は別です。
動作する可能性はあります。


返信引用
mom
 mom
(@mom)
ゲスト
結合: 9年前
投稿: 17
Topic starter  

ご連絡有難うございます。

②,③にコールバック関数の実態(A)を作ります。

(A)を①のDLLへ設定したいですが、

コールバック関数ポインタの受け渡しがどうもわからず、悩んでます。

これは、DLLを使う以上無理との事でしたが
C#で作成したDinamicLinkLibrary~Form間では行えました。

C#で作成したCOM DLLでは難しいのでしょうか?

備考:目的はDLL~アプリ間の通知になります。
   この場合SendMessageを使った方がとも考えてます。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

https://msdn.microsoft.com/ja-jp/library/d186xcf0(v=vs.110).aspx
これでいいのかな?
これだとDLLはC#ではなくなっちゃいますね。


返信引用
mom
 mom
(@mom)
ゲスト
結合: 9年前
投稿: 17
Topic starter  

ITOさん
ご連絡ありがとうございます。

はい、仰る通りです。
簡単に行える方法ですとアンマネージでの実装しかなさそうですね。

今回は簡単なMessage関数で進めようと思います。

有難うございました。


返信引用
Atata!!
 Atata!!
(@Atata!!)
ゲスト
結合: 18年前
投稿: 25
 

Atata!!です。

C++と.NET間のコールバックは実装可能です。

> これは、DLLを使う以上無理との事でしたが
> C#で作成したDinamicLinkLibrary~Form間では行えました。

上記のC#のDLLとForm間のコールバックはdelegateで実装されていると思いますが、
delegateはC++では単純な関数ポインタに変換できます。

ただ、罠がいくつかあります。
まずは、delegateでコールバック関数を定義したC# COM DLLから
タイプライブラリを生成するとdelegateはCOMインターフェース呼び出しに変換されます

[ComVisible(true)]
[Guid(C1D8EC39-99AB-4633-A8D9-EFE42033AC64)]
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void Hoge();

[ComVisible(true)]
[Guid(4EA9428B-E8BA-43DB-9B91-C22933B5E825)]
public interface ICallbackTest
{
[DispId(1)]
void SetCallback(Hoge hoge);

[DispId(2)]
void TestCallback();
}

このようなコードをタイプライブラリに変換するとdelegateのHogeは_HogeというCOMイン
ターフェースに変換されます。
これをそのままC++から利用しようとすると変換された_Hogeインターフェースを実装する
必要があり、
ややめんどくさい話になります。
(↑のインターフェースはIDispatchであり、Invokeメソッドだけ実装すれば機能します
が・・・)

これを関数ポインタとして扱うためには以下のようにMarshalAs属性を付与します。

[ComVisible(true)]
[Guid(C1D8EC39-99AB-4633-A8D9-EFE42033AC64)]
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void Hoge();

[ComVisible(true)]
[Guid(4EA9428B-E8BA-43DB-9B91-C22933B5E825)]
public interface ICallbackTest
{
[DispId(1)]
void SetCallback([MarshalAs(UnmanagedType.FunctionPtr)] Hoge hoge);

[DispId(2)]
void TestCallback();
}

これで生成されるコールバックは32ビットまたは64ビットの整数になります。
ビット数は使用するTLBEXPのビット数とアンマネージDLLのビット数によって決定されま
す。
これはC++側が32ビットと64ビットの両方に対応しなければならない場合、
別々のTLBを参照しなければならないため、めんどくさいことになります。

これらの問題をすっきり解消するにはコールバック関数と言う考えを捨てて、
コールバックをCOMインターフェースとして定義した方が良いです。
MFCで実装する場合はC#側はCOMイベントとして定義した方が結果的に簡単かもしれません


返信引用
mom
 mom
(@mom)
ゲスト
結合: 9年前
投稿: 17
Topic starter  

Atata!!さん

この方法が知りたかったです!
アドバイスありがとうございます。

C++では単純な関数ポインタとして扱うにはマーシャル関数を用いるのですね。

上記の実装はC# COM DLL側のCSファイルに記述する内容でしょうか?

また、MFC側へは単純に変換したC++では単純な関数ポインタとして
扱えるということですか?


返信引用
Atata!!
 Atata!!
(@Atata!!)
ゲスト
結合: 18年前
投稿: 25
 

> 上記の実装はC# COM DLL側のCSファイルに記述する内容でしょうか?

その通りです。
適用している属性に差はあるかもしれませんが、
基本的にはCOM公開しているメソッドの引数に
MarshalAs属性を付けることが重要になります。

> また、MFC側へは単純に変換したC++では単純な関数ポインタとして
> 扱えるということですか?

これもその通りですが、32ビット環境では呼び出し規約の制限を受けます。

C#側では呼び出し規約は以下の属性で指定しています。
[UnmanagedFunctionPointer(CallingConvention.StdCall)]

この場合、C++側は__stdcall呼び出し規約で関数を宣言する必要があります。
VC++なら単純にCALLBACKキーワードを付けるのが簡単で良いです。
あとC++の場合、メンバ関数では駄目でstaticな関数でなければなりません。
この辺は通常のコールバック関数を呼び出すのと変わりません。


返信引用
mom
 mom
(@mom)
ゲスト
結合: 9年前
投稿: 17
Topic starter  

Atata!!さん

なるほど、C++/CLIを勉強しながら試してみます。

有難うございました


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

老婆心ながら、
いまからC++/CLIを勉強しても何の役にもたたないのでやめましょう。
MSさん自身が非推奨としていることを考えると
今後、この言語が使用されることはまずありえないと考えられます。
(vv;)


返信引用
mom
 mom
(@mom)
ゲスト
結合: 9年前
投稿: 17
Topic starter  

仲澤さん
ありがとうございます。

C++/CLIの技術文献が少なくなっているのは分かりますが

MSは非推奨としているのですか?

そのような内容を見つける事ができなかったので・・・。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

VS2012、VS2013で、C++/CLIプロジェクトを新規作成する
簡単な方法がないことからも明らかですが。
以下のページのVS2012の説明「統合開発環境」の項目に
はっきりとした記述があります。

https://msdn.microsoft.com/ja-jp/library/vstudio/bb531344(v=vs.110).aspx

からの抜粋・・・

・C++/CLI を使った Windows フォーム アプリケーションの作成は推奨しません。ただし
、既存の C++/CLI UI アプリケーションの保守はサポートされます。 Windows フォーム
アプリケーション、またはそのほかの .NET アプリケーション UI は、使用、C または V
isual Basic 作成する必要があります。 相互運用性の目的に制限は C++/CLI を使用しま
す。

ということですね。C++/CLIのことは忘れましょう。


返信引用
匿名
 匿名
(@匿名)
ゲスト
結合: 1秒前
投稿: 0
 

仲澤さん

仰る通り、C++/CLIに関する最近の情報は少なすぎますね。

また記事の抜粋有難うございます。

なるべく避けてとおる様に進めてみます^^

本当に色々と有難うございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました