トップ回答者
C#(DLL)からC++(exe)の関数の呼び出しを行いたい

質問
-
お世話になります。
C#からC++(EXE)の関数呼び出しについて、教えてください。
Visual Studio 2010
Win32(C++)からWPFのコンテンツをホストして画面を作成しています。
C++側はコンパイルに/clrオプションを設定してあります。
C++側はExeで作成し、C#側はDLLで作成してあります。
C++側=====================
ref class Globals
{
public:
static System::Windows::Interop::HwndSource^ gHwndSource;
static WPFControls::TEST01^ gwcTest;
};
HWND GetHwnd(HWND parent, int x, int y, int width, int height)
{
System::Windows::Interop::HwndSourceParameters^ sourceParams =
gcnew System::Windows::Interop::HwndSourceParameters
("MFCWPFApp");
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;
Globals::gHwndSource =
gcnew System::Windows::Interop::HwndSource(*sourceParams);
Globals::gwcTest = gcnew WPFControls::TEST01();
FrameworkElement^ myPage = Globals::gwcTest;
Globals::gHwndSource->RootVisual = myPage;
return (HWND) Globals::gHwndSource->Handle.ToPointer();
}C#側=====================
namespace WPFControls
{
public partial class TEST01 : UserControl
{
InitializeComponent();
}
public void AAA()
{
}
}C++側からC#側の関数の呼び出しは行えます。(Globals::gwcTest->AAA())
C#側からC++の関数の呼び出しを行う方法をご教示いただけますか。
よろしくお願いいたします。
回答
-
C#から呼ばせたい関数をデリゲートで渡して呼ばせれば普通にできますが…
#MFCやWPFを用意するのが面倒なのでC++/CLIコンソールアプリと単純なC#DLLで
#include "stdafx.h" #include <locale> #include <iostream> #include <vcclr.h> #include <tchar.h> using namespace System; void CallBacked(System::Object^ param) { if (param != nullptr) { System::String^ str = param->ToString(); pin_ptr<const wchar_t> ps= PtrToStringChars(str); const wchar_t* pc = ps; std::wcout << pc << std::endl; } } void EventCallback(System::Object^ sender, System::EventArgs^ e) { if (e != nullptr) { System::String^ str = e->ToString(); pin_ptr<const wchar_t> ps = PtrToStringChars(str); const wchar_t* pc = ps; std::wcout << pc << std::endl; } } int main(array<System::String ^> ^args) { std::locale::global(std::locale("")); System::Action<System::Object^>^ callBack = gcnew System::Action<System::Object^>(&CallBacked); System::EventHandler<System::EventArgs^>^ handler = gcnew System::EventHandler<System::EventArgs^>(&EventCallback); ClassLibrary1::Class1^ c = gcnew ClassLibrary1::Class1(); c->AAA(callBack); c->CustomEvent += handler; c->AAA(); return 0; }
C#
using System; namespace ClassLibrary1 { public class Class1 { public void AAA(Action<object> callBack) { callBack("てすと"); } public void AAA() { var ce=CustomEvent; if(ce != null) { ce(this,EventArgs.Empty); } } public event EventHandler<EventArgs> CustomEvent; } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク がちゃぽん 2018年12月21日 7:35
すべての返信
-
了解しました。残念ですが回答としては、
・そのような事はやるべきではありません。(ほぼ不可能と言ってもよい)
となります。理由は色々とあるのですが、一つだけ上げると
・Windows OSはそのような動作を前提として設計されていない。
からですね。
>C(EXE)→C#(DLL)→C(EXE)と実行したいです。
>C#側で実施した値をC++側の画面に反映する必要があるため、
>C#側でC++の関数を呼び出したいです。
この様な場合は、呼びたしたいEXEの機能を発現するために、DLL側はEXEに対して
(a)戻り値(構造でも可)に意味を持たせる。
(b)実行したい意味のメッセージを送付する。
等の方法をとることが多いです。
OS自体もその方法を多く使用しています。- 編集済み 仲澤@失業者 2018年12月21日 3:00
-
・そのような事はやるべきではありません。(ほぼ不可能と言ってもよい)
ここは賛同します。
・Windows OSはそのような動作を前提として設計されていない。
一応、実現可能なように設計されています。
まず、質問の.NETアセンブリであればEXEもDLLも同じ形式であり、DLLからEXEの呼び出しは普通に可能です。また、相互参照そのものも解決不可能なわけではありません。例えばSystem.dllはXMLファイル操作のためにSystem.XML.dllを参照していますが、System.XML.dllももちろんSystem.dllを参照しています。
ちなみにネイティブでもDLLがEXEを参照可能です。例えばnetsh.exeを拡張する際、RegisterContext関数で登録するDLLを作成しますが、この関数自身はnetsh.exeに含まれています。
-
C#から呼ばせたい関数をデリゲートで渡して呼ばせれば普通にできますが…
#MFCやWPFを用意するのが面倒なのでC++/CLIコンソールアプリと単純なC#DLLで
#include "stdafx.h" #include <locale> #include <iostream> #include <vcclr.h> #include <tchar.h> using namespace System; void CallBacked(System::Object^ param) { if (param != nullptr) { System::String^ str = param->ToString(); pin_ptr<const wchar_t> ps= PtrToStringChars(str); const wchar_t* pc = ps; std::wcout << pc << std::endl; } } void EventCallback(System::Object^ sender, System::EventArgs^ e) { if (e != nullptr) { System::String^ str = e->ToString(); pin_ptr<const wchar_t> ps = PtrToStringChars(str); const wchar_t* pc = ps; std::wcout << pc << std::endl; } } int main(array<System::String ^> ^args) { std::locale::global(std::locale("")); System::Action<System::Object^>^ callBack = gcnew System::Action<System::Object^>(&CallBacked); System::EventHandler<System::EventArgs^>^ handler = gcnew System::EventHandler<System::EventArgs^>(&EventCallback); ClassLibrary1::Class1^ c = gcnew ClassLibrary1::Class1(); c->AAA(callBack); c->CustomEvent += handler; c->AAA(); return 0; }
C#
using System; namespace ClassLibrary1 { public class Class1 { public void AAA(Action<object> callBack) { callBack("てすと"); } public void AAA() { var ce=CustomEvent; if(ce != null) { ce(this,EventArgs.Empty); } } public event EventHandler<EventArgs> CustomEvent; } }
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答としてマーク がちゃぽん 2018年12月21日 7:35