C++/CLIでアンマネージクラスの非静的メンバをデリゲートにする
ボタンのClickイベントに設定しようとしたらどつぼに嵌ったのでメモ。
/** * 参照設定: System , System.Windows.Forms **/ using namespace System::Windows; class UnManage { public: UnManage(); void callback(System::Object ^sender, System::EventArgs ^e); }; UnManage::UnManage() { Forms::Button ^button1 = gcnew Forms::Button(); //error C3364: 'System::EventHandler' : delegate コンストラクタの引数が無効です。 // デリゲート ターゲットはメンバ関数のポインタである必要があります。 button1->Click += gcnew System::EventHandler(this, &UnManage::callback); } void UnManage::callback(System::Object ^sender, System::EventArgs ^e) { //実際の処理 }
まあよく考えれば当然なエラーではあるわけだけども、なんせ説明文がわかりにくい。アンマネージクラスの非静的メンバ関数(staticじゃないやつ)はデリゲートに出来ない、ということに辿り着くのにだいぶ時間食った。
993-997に解があったんだけど、boost入れるのもアレなのでその場しのぎのラッパークラスを作る。
#include <vcclr.h> /** * 参照設定: System , System.Windows.Forms **/ using namespace System::Windows; ref class ManageClass; //前方宣言 class UnManage { public: UnManage(); void callback(System::Object ^sender, System::EventArgs ^e); private: gcroot<ManageClass ^> wrap; }; ref class ManageClass { public: UnManage *obj; void Do (System::Object ^sender, System::EventArgs ^e) { this->obj->callback ( sender, e ); } }; UnManage::UnManage() { Forms::Button ^button1 = gcnew Forms::Button(); this->wrap = gcnew ManageClass(); this->wrap->obj = this; //OK button1->Click += gcnew System::EventHandler( (ManageClass^)wrap, &ManageClass::Do); } void UnManage::callback(System::Object ^sender, System::EventArgs ^e) { //実際の処理 }
まあラッパーのほうで実処理しちゃってもいいけども。