错误C2664无法将参数1从'std :: string(__thiscall ClassName :: *)(std :: string)'转换为'std :: string(__ cdecl *)(std :: string)

时间:2013-06-19 10:43:06

标签: visual-c++ boost event-handling c++-cli function-pointers

我正在创建一个非托管应用程序来处理在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时,

  1. 我将我的EventHandlerWrapper订阅到c#事件

  2. 将功能指针连接到我的增强信号signalEvent。

  3. 设置CSharp类的名称属性

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

    void EventHandlerWrapper(string value)

    {
    
    if(signalEvent.connected())
    

    { signalEvent(值); }

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

    P.S ::所有其他设计方法的耳朵。

1 个答案:

答案 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

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

如果这可以解决您的问题,请告诉我......