トップ回答者
C#でDLLからEXE内のメソッドをコールする場合の書き方について

質問
-
現在、C++で書かれた処理を参考に、C#で実装するということを行っています。
その中で、DLLからEXE内のメソッドをコールしている部分があり、それのC#での実装方法で悩んでいます。
また、DLLは外部提供されたもので、中身をいじることができません。具体的には下記ソース。
--------------------
【C++のサンプル】
・abc.h
void __declspec(dllexport) __cdecl XXXXX(void *p);・abc.cpp
void XXXXX(void *p){
//ここに処理を書く
}
--------------------これを、C#にしたいのです。
いろいろ調べてみて、delegateや、interfaceなど試してはみたのですが、うまくいきませんでした。
DLLImportがあるので、DLLExport的なものがあってもいいと思うのですが、何か実装する方法などございますでしょうか。
どなたか、ご教授いただけますと幸いです。
宜しくお願い致します。
回答
-
「EXE が DLL にコールバック関数を渡すのでなく、EXE が dllexport を?」と思ったのですが、現在は次のようなことをしているのでしょうか?
EXE側の関数をDLLから呼び出す
http://66272.diarynote.jp/201008242017255077/
だとすると、普通に考えれば dllexport をしている部分を C++/CLI でラップしてしまえば良さそうに思います。
あるいは、次のスレッドが興味深いかもしれません。
(添付されているテンプレートは、出力ファイルが EXE だと "cannot create unmanaged exports." と怒られてしまいましたが。)
Make C# DLL methods callable like C-style DLLs | Coffeehouse | Forums | Channel 9
http://channel9.msdn.com/Forums/Coffeehouse/Do-you-know-a-tool-to-automate-making-C-DLLs-exports-callable-from-native-code- 回答としてマーク ゆうきくん 2013年2月21日 12:34
すべての返信
-
佐祐理様
返信ありがとうございます。
DLLからEXEを呼びたいのではなく、EXE内のメソッドを呼びたいのです。具体的には、EXE(これは自作)を実行。⇒待ちうけ状態。
その状態のときに、別の端末から接続されたときや、
キーボードなど外部入力機器からの入力が確認できたときに、
DLLがそのメソッドをコールするということをします。C++のサンプルを見ると、グローバルな関数として、
その関数(XXXXX)が実装されているだけでした。わかりづらい説明で申し訳ございません。
不明な点はどんどん聞いていただいて構いませんので、
お手数をおかけしますが、宜しくお願い致します。 -
「EXE が DLL にコールバック関数を渡すのでなく、EXE が dllexport を?」と思ったのですが、現在は次のようなことをしているのでしょうか?
EXE側の関数をDLLから呼び出す
http://66272.diarynote.jp/201008242017255077/
だとすると、普通に考えれば dllexport をしている部分を C++/CLI でラップしてしまえば良さそうに思います。
あるいは、次のスレッドが興味深いかもしれません。
(添付されているテンプレートは、出力ファイルが EXE だと "cannot create unmanaged exports." と怒られてしまいましたが。)
Make C# DLL methods callable like C-style DLLs | Coffeehouse | Forums | Channel 9
http://channel9.msdn.com/Forums/Coffeehouse/Do-you-know-a-tool-to-automate-making-C-DLLs-exports-callable-from-native-code- 回答としてマーク ゆうきくん 2013年2月21日 12:34
-
totojo様
返信ありがとうございます。
そうです!
リンクに記載されている「EXE側の関数をDLLから呼び出す」がやりたいことです。
それのC#版で頭を悩ませているのですが・・・> dllexport をしている部分を C++/CLI でラップして
なるほど。
C#だけでなんとかしようとしていたから思いつかなかったですね。
明日、試してみようと思います。もう一個のchannel9の方も確かに興味深いですね。
DLLExportってのができるんですかね。
英語なので、解釈するのに時間がかかるかもですが、こちらも目を通してみようと思います。いろいろと参考となるものを探していただいて、ありがとうございます。
また確認等できましたら、結果を書き込みさせていただきますので、
少々お時間をください。
宜しくお願い致します。 -
まだこの説明でもわかりませんでしたが、totojoさんのリプライでようやく分かった気がします。「EXE内のメソッドを呼びたい」ではなくその真逆の「DLLから呼び出されるメソッドを作りたい」ですか? 何を作りたいのか、ご自身で理解されているのか怪しいです。
それはそうと、totojoさんの書かれているようなことをしたいのでしょうか? 念のため確認ですが、 dumpbin /dependents "当該DLLファイル" の実行結果にEXEファイル名が含まれているのか、また dumpbin /exports "EXEファイル" の実行結果に呼び出される関数が列挙されているのか、を見ていただけますでしょうか。
これらにきちんと列挙されているのであれば、totojoさんの書かれている方法が必要であり、そうなるとEXEはC#では書けず、C++やC++/CLIで書く必要があります。そうでなく関数ポインターを渡しているだけであれば、Marshal.GetFunctionPointerForDelegate メソッドで関数ポインターを作成し、DLLに渡すだけで済みます。
-
totojo様
佐祐理様いろいろご助力いただき、ありがとうございます。
佐祐理様が教えてくださった、dumpbin、確認してみました。
EXEファイルの名前は出てきませんでしたので、関数ポインタを渡す方法を試してみたのですが、
exportされたメソッドはコールされませんでした。ですが、別の方法として、totojo様が教えてくださった「C++/CLIでラップする」とはやり方が違うのですが、
それを言葉を参考に、C++でDLLとEXEの橋渡しをするDLLを作るという対処で実装することができました。橋渡しをするDLLとは、自分の扱いやすいように、コールバックなどを実装したものです。
EXEの起動時に、コールバックメソッドを"橋渡しDLL"に渡してあげるようにし、
"橋渡しDLL"は、DLLからメソッドがコールされたら、コールバックメソッドを実行するという流れです。本来であれば、教えていただいた手法をいろいろと試してみたいところではありますが、
私の業務スケジュールの関係と、技術力不足ということもあり、ひとまずこの方法で解決とします。
ありがとうございました。