错误:'指向成员的指针对托管类无效'

Posted

技术标签:

【中文标题】错误:\'指向成员的指针对托管类无效\'【英文标题】:ERROR: 'a pointer to member is not valid for a managed class'错误:'指向成员的指针对托管类无效' 【发布时间】:2018-02-16 11:31:11 【问题描述】:

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

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(我的主要用户界面类)进行编码,接下来由谁来做:

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); 行,它表示指向成员的指针对于托管类无效。当我在托管课程中时,执行此回调分配的正确形式是什么?我认为我应该找到一种将委托转换为函数指针的方法,但我也不确定。

提前谢谢你。

编辑:我尝试将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 : cannot convert parameter 1 from 'System::IntPtr' to 'PNIO_CBF_DATA_WRITE''

【问题讨论】:

【参考方案1】:

您可能会考虑重新阅读 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,只需将其重新路由到您定义的另一个函数即可。

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

亲切的问候

附言我想用低质量标记你的问题。因为有文档可以阅读/谷歌并从中学习。您应该花点时间,善意地将您最近四个问题的一些答案标记为正确答案。

【讨论】:

很抱歉之前没有标记你的答案,我只在周一到周五访问我的帐户。我有两个问题:(1)您所指的 __stdcall 兼容性是什么?换句话说......如果我不使用__stdcall,兼容性问题会是什么? (2)当你谈到“来源”时,你是什么意思?复合 DLL 的库代码还是什么?谢谢杰克! 1) 请重新阅读文档,那里有提到。基本上从本机代码调用到托管代码必须使用这个__stdcall。如果你不使用它,你会在某个地方出现错误,使用数据提供接口相当快。一般重读调用约定。 2) 有时您会从同事、进程或以前的固定版本中获得预编译的库。你得到了头文件,但没有实现。然后,如果不从那些人那里获得帮助,您就无法更改调用约定。 对不起@JackGrinningCat,但我完全按照文档所说的做,我得到了下一个错误:oi66.tinypic.com/2gtdu6a.jpg 我也使用 __cdecl 检查过,但出现了同样的错误。 typedef PNIO_IOXS (__stdcall *PNIO_CBF_DATA_WRITE) 您是否重新编译了调用 PNIO_CBF_DATA_WRITE 的 c 代码

以上是关于错误:'指向成员的指针对托管类无效'的主要内容,如果未能解决你的问题,请参考以下文章

指向成员转换的指​​针

将指向 int 数组的指针传递给成员函数,错误:数组下标的无效类型“int [int]”

这个指向成员转换的指​​针有啥问题?

C ++从类外部设置指向结构中函数成员的指针

指向基类错误成员函数的指针[关闭]

指向托管类成员的指针