0

我正在制作一个非托管应用程序来处理在 c# 中触发的事件。仅供参考:: 我想在 C# 类中的 Name 属性更改时处理自定义事件。我浏览了以下链接:

关于将指向成员函数的指针作为参数传递的说明

类似于我的问题。但无法理解解决方案

现在,在 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 时,

  1. 我将 EventHandlerWrapper 订阅到 ac# 事件

  2. 将函数指针连接到我的升压信号signalEvent。

  3. 设置 CSharp 类的 Name 属性

    当设置 Name 属性时,触发 c# 事件,执行 Wrapper.cpp 中的 EventHandlerWrapper 方法。看起来像这样::

    void EventHandlerWrapper(字符串值)

    {
    
    if(signalEvent.connected())
    

    { 信号事件(值);}

由于某些原因,我不能将我的 FunctionToBePointed(std::string) 方法作为非成员函数。

PS:: 任何其他设计方法的耳朵。

4

1 回答 1

1

在您的实际用例中,您可以简单地将 FunctionToBePointed 设为静态方法吗?

static std::string Class1::FunctionToBePointed(std::string msg)
{
   return msg;
}

如果是,您的代码应该可以工作。

原因是实例方法使用隐藏的this指针隐式调用,这是thiscall调用约定,而静态方法仅使用cdecl约定,因为它们不适用于任何实例。

编辑:

带有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 包装器:

包装器.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();
};

包装器.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

我有一个更通用的解决方案,但它真的很难看。:(

让我知道这是否能解决您的问题...

于 2013-06-19T13:00:15.747 回答