我正在创建一个非托管应用程序来处理在c#中触发的事件。 FYI ::我想在C#类中更改我的Name属性时处理自定义事件。 我已经浏览了以下链接:
Explanation about passing pointer to member function as parameter
Something similar to my problem.But couldn't understand the solution
现在, 在NativeApp.cpp中,我有一个成员函数,它作为函数指针作为参数传递给c ++ / CLI包装器中的方法
//NativeApp.cpp
std::string Class1::FunctionToBePointed(std::string msg)
{
return msg;
}
void Class1::NativeMethod()
{
UnmanagedWrapperClass* unmanagedWrapperClass=new UnmanagedWrapperClass();
unmanagedWrapperClass->WrapperMethod(&Class1::FunctionToBePointed,"Hello")
}
在Wrapper.h中,
//Wrapper.h
class __declspec(dllexport) UnmanagedWrapperClass
{
boost::signals2::signal<void(std::string)>signalEvent;
void WrapperMethod(std::string (*GetCallBack)(std::string),std::string value);
}
当我从NativeApp.cpp调用WrapperMethod时,
我将我的EventHandlerWrapper订阅到c#事件
将功能指针连接到我的增强信号signalEvent。
设置CSharp类的名称属性
当设置了Name属性时,会触发c#事件,执行Wrapper.cpp中的EventHandlerWrapper方法。看起来像这样::
void EventHandlerWrapper(string value)
{
if(signalEvent.connected())
{ signalEvent(值); }
由于某些原因,我不能将我的FunctionToBePointed(std :: string)方法作为非成员函数。
P.S ::所有其他设计方法的耳朵。
答案 0 :(得分:1)
在您真实的用例中,您可以简单地将FunctionToBePointed设为静态方法吗?
static std::string Class1::FunctionToBePointed(std::string msg)
{
return msg;
}
如果是,您的代码应该有效。
原因是使用隐藏此指针隐式调用实例方法,这是 thiscall < / em>调用约定,而静态方法只使用 cdecl 约定,因为它们不适用于任何实例。< / p>
修改强>
Boost :: bind 的示例:
MyClass C#类:
using System;
using System.ComponentModel;
public class MyClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate{};
private string name;
public string Name
{
get
{
return name;
}
set
{
if (name != value)
{
name = value;
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
C ++ / CLI包装器:
Wrapper.h:
class WrapperPrivateStuff;
class __declspec(dllexport) UnmanagedWrapperClass
{
private: WrapperPrivateStuff* _private;
public: void changeIt(std::string newName);
public: void WrapperMethod(boost::function<std::string(std::string)> GetCallBack);
public: UnmanagedWrapperClass();
};
Wrapper.cpp:
#using "MyClass.dll"
#include <boost/signals2.hpp>
#include <boost/bind.hpp>
#include "Wrapper.h"
#include <msclr\auto_gcroot.h>
#include <msclr\marshal_cppstd.h>
#include <msclr\event.h>
class WrapperPrivateStuff
{
public: boost::signals2::signal<void(std::string)>signalEvent;
public: msclr::auto_gcroot<MyClass^> a;
public: void EventHandlerWrapper(System::Object^, System::ComponentModel::PropertyChangedEventArgs^ args)
{
this->signalEvent(msclr::interop::marshal_as<std::string>(a->Name));
}
public: WrapperPrivateStuff()
{
a = gcnew MyClass();
a->PropertyChanged += MAKE_DELEGATE(System::ComponentModel::PropertyChangedEventHandler, EventHandlerWrapper);
}
BEGIN_DELEGATE_MAP(WrapperPrivateStuff)
EVENT_DELEGATE_ENTRY(EventHandlerWrapper, System::Object^, System::ComponentModel::PropertyChangedEventArgs^)
END_DELEGATE_MAP()
};
void UnmanagedWrapperClass::changeIt(std::string newName)
{
this->_private->a->Name = msclr::interop::marshal_as<System::String^>(newName);
}
UnmanagedWrapperClass::UnmanagedWrapperClass()
{
this->_private = new WrapperPrivateStuff();
}
void UnmanagedWrapperClass::WrapperMethod(boost::function<std::string(std::string)> GetCallBack)
{
_private->signalEvent.connect(GetCallBack);
}
本机应用程序test.cpp:
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include "Wrapper.h"
class Class1
{
private: std::string name;
public: Class1(std::string name)
: name(name)
{
}
public: std::string FunctionToBePointed(std::string msg)
{
std::cout << "Hey it's " << name << "! Got: " << msg << std::endl;
return msg;
}
};
int main(void)
{
UnmanagedWrapperClass wrapper;
Class1 class1("Ed");
wrapper.WrapperMethod(boost::bind(&Class1::FunctionToBePointed, &class1, _1));
wrapper.changeIt("azerty");
return 0;
}
结果:
>test.exe
Hey it's Ed! Got: azerty
我有一个更通用的解决方案,但它真的很难看。 :(
如果这可以解决您的问题,请告诉我......