错误:'指向成员的指针对托管类无效'
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 的部分文档。即使它是旧的(比如从 2006 年开始),它也不会过时。
示例。 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 代码以上是关于错误:'指向成员的指针对托管类无效'的主要内容,如果未能解决你的问题,请参考以下文章