c++从不同线程中的非托管代码调用委托

发布于 2024-10-10 10:58:52 字数 2661 浏览 8 评论 0原文

[提前致歉。我已经阅读了此处和 codeproject.com 上有关此主题的几篇帖子,但我仍然缺少一些内容。]

我有一个通知框架(类似于事件),作为用非托管 C++ 编写的遗留系统的一部分。我还有一个混合模式 DLL,其中包含向托管世界公开遗留功能的托管类。

CacheControlNotification 类是一个管理桥类,旨在将未管理事件转换为托管事件。它包含一个非托管 NativeCcmBridge 类,该类在遗留框架中注册以接收非托管消息。 NativeCcmBridge 将数据编组为托管类型,并将其传递到 CacheControlNotification,并在其中分派给感兴趣的托管方。

GetDelegateForFunctionPointer() 抛出 NotSupportedException:无法将委托从本机代码编组到除其主域之外的域中。

回调发生在源自本机代码的线程中。这个例外让我相信我的解决方案从根本上来说是有缺陷的。

任何帮助表示赞赏。谢谢。

罗伯特

public delegate void OnNotifyHandler ( ManagedCallbackMessage^ );

//
// Native class to marshal callback to managed code.   Callbacks
// in the native world are registered via an "ANativeHandler" type.
//
class NativeCcmBridge : public ANativeHandler
{
    private:
        //
        // Pointer to the managed delegate
        //
        IntPtr m_callbackPtr;


    public:
        NativeCcmBridge ( OnNotifyHandler^ callback )
        {
            m_callbackPtr = Marshal::GetFunctionPointerForDelegate(callback);
        }

        //
        // Provide implementation for pure virtual native handler
        //
        virtual void OnNotify (NativeCallbackMsg& nativeCallbackMsg)
        {
            // Convert the native message to a managed message
            ManagedCallbackMessage^ msg = new ManagedCallbackMessage( nativeCallbackMsg );

            // Now push the managed message via the delegate
            // throws NotSupportedException:  Delegates cannot be marshaled from native code into a domain other than their home domain.
            OnNotifyHandler^ callback = (OnNotifyHandler^)Marshal::GetDelegateForFunctionPointer(m_callbackPtr, OnNotifyHandler::typeid);
            callback( msg );
        }

};

//
// Managed Class to receive marshalled messages and 
// reissue in managed world.
//
public ref class CacheControlNotification
{
    public:
        CacheControlNotification()
        {
            m_callback = (OnNotifyHandler^) Delegate::CreateDelegate( OnNotifyHandler::typeid, this, "RaiseNotification" );
            m_bridge = new NativeCcmBridge( m_callback );

            // Register m_bridge the native mechanism
        }

        virtual ~CacheControlNotification () { this->!CacheControlNotification(); }
        !CacheControlNotification ()
        {
            delete m_bridge;
            m_bridge = nullptr;
        }

        event OnNotifyHandler^ OnNotify;

    protected:
        NativeCcmBridge* m_bridge;
        pin_ptr<OnNotifyHandler^> m_callback;

        void RaiseNotification ( CacheControlMessage^ msg )
        {
            OnNotify( msg );
        }
};

[Apologies in advance. I've read several postings both here and codeproject.com on this topic, but I'm still missing something.]

I have a notification framework (analogous to Events) as part of a legacy system written in unmanaged C++. I also have a mixed-mode DLL with managed classes exposing legacy functionality to the managed world.

The CacheControlNotification class is a manage bridge class intended to translate the unamanged events to managed events. It contains an unmanaged NativeCcmBridge class which is registered in the legacy framework to receive the unmanaged messages. The NativeCcmBridge marshals the data to a managed type and passes it up to the CacheControlNotification where it dispatched to interested managed parties.

GetDelegateForFunctionPointer() is throwing NotSupportedException: Delegates cannot be marshaled from native code into a domain other than their home domain.

The callbacks occur in threads originating in the native code. The exception leads me to believe my solution is fundamentally flawed.

Any help is appreciated. Thanks.

Robert

public delegate void OnNotifyHandler ( ManagedCallbackMessage^ );

//
// Native class to marshal callback to managed code.   Callbacks
// in the native world are registered via an "ANativeHandler" type.
//
class NativeCcmBridge : public ANativeHandler
{
    private:
        //
        // Pointer to the managed delegate
        //
        IntPtr m_callbackPtr;


    public:
        NativeCcmBridge ( OnNotifyHandler^ callback )
        {
            m_callbackPtr = Marshal::GetFunctionPointerForDelegate(callback);
        }

        //
        // Provide implementation for pure virtual native handler
        //
        virtual void OnNotify (NativeCallbackMsg& nativeCallbackMsg)
        {
            // Convert the native message to a managed message
            ManagedCallbackMessage^ msg = new ManagedCallbackMessage( nativeCallbackMsg );

            // Now push the managed message via the delegate
            // throws NotSupportedException:  Delegates cannot be marshaled from native code into a domain other than their home domain.
            OnNotifyHandler^ callback = (OnNotifyHandler^)Marshal::GetDelegateForFunctionPointer(m_callbackPtr, OnNotifyHandler::typeid);
            callback( msg );
        }

};

//
// Managed Class to receive marshalled messages and 
// reissue in managed world.
//
public ref class CacheControlNotification
{
    public:
        CacheControlNotification()
        {
            m_callback = (OnNotifyHandler^) Delegate::CreateDelegate( OnNotifyHandler::typeid, this, "RaiseNotification" );
            m_bridge = new NativeCcmBridge( m_callback );

            // Register m_bridge the native mechanism
        }

        virtual ~CacheControlNotification () { this->!CacheControlNotification(); }
        !CacheControlNotification ()
        {
            delete m_bridge;
            m_bridge = nullptr;
        }

        event OnNotifyHandler^ OnNotify;

    protected:
        NativeCcmBridge* m_bridge;
        pin_ptr<OnNotifyHandler^> m_callback;

        void RaiseNotification ( CacheControlMessage^ msg )
        {
            OnNotify( msg );
        }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文