ERROR: 'a pointer to member is not valid for a managed class'

ERROR: 'a pointer to member is not valid for a managed class'

我遇到了这个错误,但我不知道如何解决。这是我的代码(下面有更多详细信息):

CP1626.h

#pragma once

#include <Windows.h>
namespace CP1626{

...

//DLL functions
void setCallbackDataWriteFunc(PNIO_CBF_DATA_WRITE _ptrDataWriteFunc);

...

}

cp1626.cpp

#include "cp1626lib.h"

...

typedef void (* ptr_setCallbackDataWriteFunc)(PNIO_CBF_DATA_WRITE);
ptr_setCallbackDataWriteFunc setCallbackDataWriteFuncFunction;

...

void CP1626::setCallbackDataWriteFunc(PNIO_CBF_DATA_WRITE _ptrDataWriteFunc){
    (setCallbackDataWriteFuncFunction)(_ptrDataWriteFunc);
}

并且 PNIO_IOXS 定义为

typedef PNIO_IOXS    (*PNIO_CBF_DATA_WRITE) /* write data to IO stack (local ==> remote) */
       (PNIO_UINT32          DevHndl,       /* Handle for Multidevice */
        PNIO_DEV_ADDR      * pAddr,         /* geographical address */
        PNIO_UINT32          BufLen,        /* length of the submodule input data */
        PNIO_UINT8         * pBuffer,       /* Ptr to data buffer to write to */
        PNIO_IOXS            Iocs);         /* remote (io controller) consumer status */

然后,我使用 C++/CLI 和 .NET 编写代码,我的主要用户界面 class,接下来由谁来做:

UI_Main.h

#include "cp1626lib.h"

...


public ref class UI_Main : public System::Windows::Forms::Form{

    //Local function definition, which is assigned to callback
    PNIO_IOXS dataWriteFunc(PNIO_UINT32 DevHndl, PNIO_DEV_ADDR * pAddr, PNIO_UINT32 BufLen, PNIO_UINT8 * pBuffer, PNIO_IOXS Iocs);

    ...

    void InitCP1626(){
                ...

                CP1626::setCallbackDataWriteFunc(dataWriteFunc);

                ...
            }

}

错误在第 CP1626::setCallbackDataWriteFunc(dataWriteFunc); 行,它表示指向成员的指针对于托管 class 无效。当我在托管 class 上时,执行此回调分配的正确形式是什么?我认为我应该找到一种方法将委托转换为函数指针,但我对此也不确定。

提前致谢。

编辑:我尝试将 CP1626::setCallbackDataWriteFunc(dataWriteFunc); 行更改为 CP1626::setCallbackDataWriteFunc(Marshal::GetFunctionPointerForDelegate(del));,并使用 dataWriteFunc^ del; 格式为 delegate PNIO_IOXS dataWriteFunc(PNIO_UINT32 DevHndl, PNIO_DEV_ADDR * pAddr, PNIO_UINT32 BufLen, PNIO_UINT8 * pBuffer, PNIO_IOXS Iocs);

的代表

但也失败了。此时,错误显示“CP1626::setCallbackDataWriteFunc:无法将参数 1 从 'System::IntPtr' 转换为 'PNIO_CBF_DATA_WRITE'”

您可能会考虑重新阅读 Microsoft 的部分文档。即使它很旧(比如从 2​​006 年开始),它也不会过时。

例子。 Microsoft 记录了回调的使用。 https://msdn.microsoft.com/en-us/library/367eeye0.aspx

在您的情况下,您没有查看 GetFunctionPointerForDelegate() 返回的内容。它是一个 IntPtr。这是 Microsoft 用于将所有类型的指针包装到 .NET 的一个结构中的结构。它有方法 void* ToPointer()

PNIO_CBF_DATA_WRITE cb = static_cast<PNIO_CBF_DATA_WRITE>(IntPtr.ToPointer());  
CP1626::setCallbackDataWriteFunc(cb);

请注意,您应该使用 __stdcall 进行回调。提到它是兼容性所必需的。

typedef PNIO_IOXS (__stdcall *PNIO_CBF_DATA_WRITE)

如果您无法重新编译源代码以使用 __stdcall,只需将其重新路由到您定义的另一个函数即可。

我试图在测试项目中使用您的代码,但我不想设置为在某个独立的地方调用回调。

亲切的问候

p.s。我想用低质量标记您的问题。因为有文档可以read/google 学习借鉴。您应该慢慢来,并且非常友好地将您最近四个问题的一些答案标记为正确答案。