私はcppプロジェクト、cpp cliプロジェクト、c#winフォームプロジェクトを持っています。私は自分のネイティブのcppコードからメソッドを起動し、C#プロジェクトでそれをキャッチしたい。これどうやってするの?Cpp/Cliイベントを起動する
答えて
これらのプロジェクト間の依存関係の要件が重要なので、この質問には複数のアプローチがあります。私は、あなたが既にネイティブのC++ライブラリを持っていて、そのライブラリをC#アプリケーションで使用したいという、最も一般的な(私は推測の)ケースに答えるように試みます。このシナリオでは、C#プロジェクトはネイティブライブラリプロジェクトに依存します。このような場合、ゲートウェイcli/C++ライブラリを使用して、ネイティブC++イベントを.NETイベントに変換できます。
ここでは、完全なコードサンプルですが、その前に、注意してください。
- をそれは最短の解決策ではないかもしれないが、それは正常に動作します。また、ネイティブデータを.net型に変換する際に、より多くの制御を提供することができます。
- 私はVS 2005でこのアプローチを使用しました。その特定の相互運用性の目的のために、新しいバージョンのVSに優れた手段があるかどうかはわかりません。
- ネイティブイベントがGUIスレッド以外のスレッドからトリガーされる場合は、thatに注意してください。
ネイティブライブラリ:
#ifndef _NATIVE_CODE_H_
#define _NATIVE_CODE_H_
//NativeCode.h
//A simple native library which emits only one event.
#include <stdlib.h>
#include <iostream>
using namespace std;
#define NATIVELIBRARY_API __declspec(dllexport)
//An argument class to wrap event parameters
class NativeEventArgs{
public:
//a 32bit integer argument
//any other primitives can be here, just be careful about the byte size
int argInt32;
//null terminated ascii string
const char* argString;
//null terminated wide/unicode string
const wchar_t* argWString;
};
//A simple mechanism to fire an event from native code.
//Your library may have a DIFFERENT triggering mechanism (e.g. function pointers)
class INativeListener
{
public:
virtual void OnEvent(const NativeEventArgs& args)=0;
};
//The actual native library code, source of native events
class NATIVELIBRARY_API NativeCode
{
public:
NativeCode()
:theListener_(NULL)
{}
//Listener registration method
void registerListener(INativeListener* listener) {
theListener_ = listener;
}
//this is the very first source of the event
//native code emits the event via the listener mechanism
void eventSourceMethod() {
//... other stuff
//fire the native event to be catched
if(theListener_){
//prepare event parameters
NativeEventArgs args;
wstring wstr(L"A wide string");
string str("A regular string");
//build-up the argument object
args.argInt32 = 15;
args.argString = str.c_str();
args.argWString = wstr.c_str();
//fire the event using argument
theListener_->OnEvent(args);
}
}
private:
//native code uses a listener object to emit events
INativeListener* theListener_;
};
#endif
ゲートウェイライブラリサンプル:
//GatewayCode.h
//GatewayLibrary is the tricky part,
//Here we listen events from the native library
//and propagate them to .net/clr world
#ifndef _GATEWAY_CODE_H_
#define _GATEWAY_CODE_H_
#include "../NativeLibrary/NativeCode.h" //include native library
#include <vcclr.h> //required for gcroot
using namespace System;
using namespace System::Runtime::InteropServices;
namespace GatewayLibrary{
//.net equvelant of the argument class
public ref class DotNetEventArg{
internal:
//contructor takes native version of argument to transform
DotNetEventArg(const NativeEventArgs& args) {
//assign primitives naturally
argInt32 = args.argInt32;
//convert wide string to CLR string
argWString = Marshal::PtrToStringUni(IntPtr((void*)args.argWString));
//convert 8-bit native string to CLR string
argString = Marshal::PtrToStringAnsi(IntPtr((void*)args.argString));
//see Marshal class for rich set of conversion methods (e.g. buffers)
}
private:
String^ argString;
String^ argWString;
Int32 argInt32;
public:
//define properties
property String^ ArgString {
String^ get() {
return argString;
}
}
property String^ ArgWString {
String^ get() {
return argWString;
}
}
property Int32 ArgInt32 {
Int32 get() {
return argInt32;
}
}
};
//EventGateway fires .net event when a native event happens.
//It is the actual gateway class between Native C++ and .NET world.
//In other words, It RECEIVES NATIVE events, TRANSFORMS/SENDS them into CLR.
public ref class EventGateway {
public:
//ctor, its implementation placed below
EventGateway();
//required to clean native objects
~EventGateway();
!EventGateway();
//the SENDER part
//.net event stuff defined here
delegate void DotNetEventHandler(DotNetEventArg^ arg);
event DotNetEventHandler^ OnEvent;
private:
//our native library code
//notice you can have pointers to native objects in ref classes.
NativeCode* nativeCode_;
//the required device to listen events from the native library
INativeListener* nativeListener_;
internal: //hide from .net assembly
//the RECEIVER part, called when a native event received
void OnNativeEvent(const NativeEventArgs& args){
//you can make necessary transformation between native types and .net types
//create .net argument using native argument
//required conversion is done by DotNetEventArg class
DotNetEventArg^ dotNetArgs = gcnew DotNetEventArg(args);
//fire .net event
OnEvent(dotNetArgs);
}
};
}
//A concrete listener class. we need this class to register native library events.
//Its our second gateway class which connects Native C++ and CLI/C++
//It basically gets events from NativeLibary and sends them to EventGateway
class NativeListenerImp : public INativeListener {
public:
NativeListenerImp(gcroot<GatewayLibrary::EventGateway^> gatewayObj){
dotNetGateway_ = gatewayObj;
}
//this is the first place we know that a native event has happened
virtual void OnEvent(const NativeEventArgs& args) {
//inform the .net gateway which is responsible of transforming native event to .net event
dotNetGateway_->OnNativeEvent(args);
}
private:
//class member to trigger .net gateway.
//gcroot is required to declare a CLR type as a member of native class.
gcroot<GatewayLibrary::EventGateway^> dotNetGateway_;
};
////ctor and dtors of EventGateway class
GatewayLibrary::EventGateway::EventGateway()
{
nativeCode_ = new NativeCode();
//note; using 'this' in ctor is not a good practice
nativeListener_ = new NativeListenerImp(this);
//register native listener
nativeCode_->registerListener(nativeListener_);
}
GatewayLibrary::EventGateway::~EventGateway()
{
//call the non-deterministic destructor
this->!EventGateway();
}
GatewayLibrary::EventGateway::!EventGateway()
{
//clean up native objects
delete nativeCode_;
delete nativeListener_;
}
#endif
そして、C#での最終的なアプリケーション(または他の.NET言語で):
//Program.cs
//C# the final evet consumer application
using System;
using System.Collections.Generic;
using System.Text;
using GatewayLibrary;
namespace SharpClient
{
class Program
{
static void Main(string[] args)
{
//create the gateway
EventGateway gateway = new EventGateway();
//listen on .net events using the gateway
gateway.OnEvent += new EventGateway.DotNetEventHandler(gateway_OnEvent);
}
static void gateway_OnEvent(DotNetEventArg args)
{
//use the argument class
Console.WriteLine("On Native Event");
Console.WriteLine(args.ArgInt32);
Console.WriteLine(args.ArgString);
Console.WriteLine(args.ArgWString);
}
}
}
あなたの答えをありがとう。 GatewayListenerImpとは何ですか?ビジュアルスタジオはそれを知らない。 (VS2010) –
OK、私は自分の答えを編集しました。それは 'NativeListenerImp'でなければなりません。私は書式設定中に間違いを犯したようです。 – xaero99
ありがとうございました。それは働いています –
- 1. 別のスレッドのイベントを起動する
- 2. アプリケーション起動イベントを検出する
- 3. Profile_OnMigrateAnonymousイベントを複数回起動する
- 4. サブクラスランタイムタイプのイベントを起動
- 5. 起動時にSizeChangedイベントを避ける
- 6. 手動でdatepickerのonselectイベントを起動する
- 7. イベントを起動できない
- 8. OracleDependencyがイベントを起動しない
- 9. 値変更のイベントを起動
- 10. バックボーンルータはイベントを起動しません
- 11. iphone - イベントをすぐに起動する方法
- 12. イベントが発生する前にjavascriptを起動します
- 13. jqGrid formatCellイベントが起動しない
- 14. Visual Studio 2010 - C#UserControlイベントの起動
- 15. Phonegapイベントが起動しない
- 16. django jquery readyイベントが起動しない
- 17. jqGridイベントが起動しない
- 18. GWT OnScrollイベントは起動しません
- 19. WPF StoryBoard.Completedイベントが起動しない
- 20. onLoadとonunloadイベントが起動しない
- 21. Window GotFocusイベントが起動しない
- 22. ASP.Net Session_Startイベントが起動しない
- 23. "backbutton"イベントは起動しません
- 24. 操作イベントが起動しない
- 25. RadioButtonList SelectedIndexChangedイベントが起動しない
- 26. Plupload -FileUploadedイベントが起動されない
- 27. BackgroundWorkerイベントが起動しない
- 28. DOMContentLoadedイベントが起動しない
- 29. PhoneGapイベントがiPhoneで起動しない
- 30. OnCheckedChangedイベントが起動しない
これは相互運用性の問題ですので、このようにタグ付けすることをお勧めします。[ここ](http://msdn.microsoft.com/en-us/library/2x8kf7zx(v = vs80).aspx)forピンボケの情報 – ldgorman