如何从带有复杂参数的本机代码中调用委托 [英] How to call delegate from native code with complex argument

查看:87
本文介绍了如何从带有复杂参数的本机代码中调用委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好.

我有一个C ++ CLI项目,该项目与一些通讯库链接,该通讯库生成带有指向非托管数据结构(UnmanagedState)的指针的回调,我需要将其转换为托管类.

我有一个非托管类,可以接收这些回调(UnmanagedClass),并且我想使用一个回调,该回调将使用委托函数将托管类注册到该回调.
这是我的问题:我试图将指向非托管结构的指针传递给委托,并收到_crtIsValidHeapPointer(puserdata)错误消息.
我认为,UnmanagedStatecontai结构具有复杂的成员并且因此回调包含一个复杂的参数这一说法是有问题的-但也许我错了.

无论如何,这里是代码的主要部分:
如您所见,UnmanagedState包含一个ID字段,该字段很复杂.当调用委托时,纯(布尔)的字段被读取为正常,但是当读取ID()时,我得到了断言.

非托管类:
UnManaged.cpp

Hi All.

I have a C++CLI project which is linked with some communication lib that generates callbacks with pointers to unmanaged data structures (UnmanagedState) that I need to translate to managed classes.

I have an unamanaged class that recieves these callbacks (UnmanagedClass) and I wanted to use a callback that a managed class will be registered to using a delegate function.

Here is my problem: I have tried to pass the pointer to the unmanaged structure to the delegate and got _crtIsValidHeapPointer(puserdata) error message.
I think that the face that the UnmanagedStatecontai structure has complex members and therefore the callback contains a complex argument is problematic - but maybe Im wrong.

anyways here are the main parts of the code:
as you can see, the UnmanagedState contains an ID field which is complex. when the delegate is called, the fields that are plain (bool) are read ok, but when ID() is read I get the assertion.

unmanaged class:
UnManaged.cpp

void CUnmanagedConnector::AddCallback(UnmanagedStateHandlerCB cb)//, void *usr)
{
    m_Handler = cb;
}



//这是非托管类如何使用它收到的回调的方法:



//here is how the unmanaged class uses the callbacks it recieves:

void CUnmanagedConnector::StateCB (UnmanagedState* pStateEvent, void *usr)
{
    CUnmanagedConnector* m = (CUnmanagedConnector*)usr;
    if(m)
        m->StateEventHandler(pStateEvent);
}

void CUnmanagedConnector::StateEventHandler (UnmanagedState *pState)
{
    if(!pPdu)
        return;
    m_Handler(pState, m_User);


}

UnManaged.h

//回调:
typedef void(* UnmanagedStateHandlerCB)(UnmanagedState * pStateEvent,void * usr);

现在是托管类:

Managed.cpp


}

UnManaged.h

// the callback:
typedef void(*UnmanagedStateHandlerCB )(UnmanagedState* pStateEvent, void *usr);

now the managed class:

Managed.cpp

ManagedClass::ManagedClass()
    {
        m_pCUnmanagedConnector = new CUnmanagedConnector();
        // Create the delegate from a member function

        updateStateCB = gcnew UpdateStateDelegate(this, &ManagedClass::UpdateStateCB);
        // As long as this handle is alive, the GC will not move or collect the delegate
        // This is important, because moving or collecting invalidate the pointer
        // that is passed to the native function below

        stateUpdateHandle = GCHandle::Alloc(updateStateCB);
        selfHandle = GCHandle::Alloc(this);
        // This line will actually get the pointer that can be passed to
        // native code
        IntPtr ptr = Marshal::GetFunctionPointerForDelegate(updateStateCB);
        m_pCUnmanagedConnector ->AddCallback(static_cast<StateHandlerCB>(ptr.ToPointer()) 
    }





void ManagedClass::UpdateStateCB(UnmanagedState* pStateEvent)
    {
        this->ValidateState(pStateEvent);
    }

    void ValidateState(UnmanagedState* pStateEvent)
    {
        //This works
        if (pStateEvent->IsNewState())
            return;
       //But this causes the assertion!!!
       if (pStateEvent->StateId.ID().getId() < 0)
            return;

    }





Managed.h

//代表:





Managed.h

//the delegate:

public delegate void UpdateStateDelegate(UnmanagedState* pStateEvent);





public ref class ManagedClass
    {
        private:



            CUnmanagedConnector* m_pCUnmanagedConnector;

            GCHandle stateUpdateHandle;

            UpdateStateDelegate^ updateStateCB;



        public:

            ManagedClass();

            void UpdateStateCB(UnmanagedState* pState);

            void ValidateState(UnmanagedState* pState);

    };









public class UnmanagedState
{
    public:

    bool IsNewState();

    StateID ID();
};









class StateID
{
public:

    StateID ();

    bool            operator<(const StateID& right) const;
    bool            operator==(const StateID& src) const;

    std::string     string() const;

    bool            IsNull();
    void            SetAsNull();


    static const StateID& nullId();

    const StateID & getID() {return m_StateParentId.m_ID;}

    CStateParentId  m_StateParentId
    int m_nInstance; // instance of state
};





非常感谢.





Thanks a lot.

推荐答案

您还必须确保正确定义诸如对齐之类的选项,因为.NET和非托管代码之间的许多默认值是不同的. >
我建议您仔细检查您的选择,尤其是与您的非托管内容相关的大小,资格和调用约定.
You also have to ensure that options such as the alignment are defined correctly since many defaults are different betwenn .NET and unmanaged code.

I would recommand you to check your option carefully and particulary size, aligment and calling convention related to your unmanaged stuff.


这篇关于如何从带有复杂参数的本机代码中调用委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆