来自C+的回调+;到C#

来自C+的回调+;到C#,c#,c++,C#,C++,我有一个C++的主题/观察者系统: #include <vector> class IObserver { public: virtual void valueChanged(float pos) = 0; }; class Subject { public: static Subject *instance(); void subscribe(IObserver *observer); private: static Subject*

我有一个C++的主题/观察者系统:

#include <vector>
class IObserver
{
public:
    virtual void valueChanged(float pos) = 0; 
};

class Subject
{
public:
    static Subject *instance();
    void subscribe(IObserver *observer);
private:
    static Subject*                    m_instance;
    std::vector<IObserver*>            m_observers;
};

如何将C成员函数转换为C++函数指针,调用最后一个函数?

< P> C不能实现C++接口,这需要从C++中完成。

您可以使用C++/CLI来创建一个Simm观测器,实现接口,也可以理解C++代表,或者可以使用C++标准来实现一个Simm观测器实现接口并调用函数指针;C#委托可以转换为函数指针

最后一种方法是C++代码使用一个完整的COM接口(IDL),其中C++可以实现,而不是一个最小的C++接口。


对于带有函数指针的新代码:

typedef void (*ValueChangedFunc)(float pos);
void SubscribeTovalueChanged(ValueChangedFunc func); // global but works on singleton

首先,在C++端指定调用约定。< /P>

typedef void (__stdcall *ValueChangedFunc)(float pos);
void __stdcall SubscribeToValueChanged(ValueChangedFunc func); // global but works on singleton
然后声明一个与函数指针typedef匹配的委托

[UnmanagedFunctionPointer(CallingConvention.Stdcall)]
delegate void ValueChangedFunc(float);
然后声明使用它的函数:

[DllImport(...)]
void SubscribeToValueChanged(ValueChangedFunc func);
请注意,本机代码中使用的函数指针对垃圾收集器不可见。只要函数指针被保存,就要保持委托的生存性。/< P> < P> C不能实现C++接口,这需要从C++ +< /P>中完成。

您可以使用C++/CLI来创建一个Simm观测器,实现接口,也可以理解C++代表,或者可以使用C++标准来实现一个Simm观测器实现接口并调用函数指针;C#委托可以转换为函数指针

最后一种方法是C++代码使用一个完整的COM接口(IDL),其中C++可以实现,而不是一个最小的C++接口。


对于带有函数指针的新代码:

typedef void (*ValueChangedFunc)(float pos);
void SubscribeTovalueChanged(ValueChangedFunc func); // global but works on singleton

首先,在C++端指定调用约定。< /P>

typedef void (__stdcall *ValueChangedFunc)(float pos);
void __stdcall SubscribeToValueChanged(ValueChangedFunc func); // global but works on singleton
然后声明一个与函数指针typedef匹配的委托

[UnmanagedFunctionPointer(CallingConvention.Stdcall)]
delegate void ValueChangedFunc(float);
然后声明使用它的函数:

[DllImport(...)]
void SubscribeToValueChanged(ValueChangedFunc func);

请注意,本机代码中使用的函数指针对垃圾收集器不可见。您有责任在函数指针存储期间保持代理活动。

非常感谢Ben!关于将C#委托转换为函数指针。我该怎么做?@Andy:这会给我一个IntPtr。如何将其转换为void*并调用C函数:void subscribe(void*p)?@Andy:(1)不要。只需在p/invoke声明中使用
IntPtr
。(2)
void*
不是函数指针类型。
Marshal.GetFunctionPointerForDelegate
的妙处在于它不需要单例;JIT编译器生成包含对特定对象的引用的本机代码,并转发给该对象上的实例方法。(3) 更好的是,在p/invoke声明中编写一个委托类型。p/invoke将为您调用
Marshal.GetFunctionPointerForDelegate
。非常感谢Ben!关于将C#委托转换为函数指针。我该怎么做?@Andy:这会给我一个IntPtr。如何将其转换为void*并调用C函数:void subscribe(void*p)?@Andy:(1)不要。只需在p/invoke声明中使用
IntPtr
。(2)
void*
不是函数指针类型。
Marshal.GetFunctionPointerForDelegate
的妙处在于它不需要单例;JIT编译器生成包含对特定对象的引用的本机代码,并转发给该对象上的实例方法。(3) 更好的是,在p/invoke声明中编写一个委托类型。p/invoke将为您调用
Marshal.GetFunctionPointerForDelegate