简体   繁体   中英

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

I'm getting this error and I don't know how to solve it. This is my code (more details below):

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);
}

And with PNIO_IOXS defined as

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 */

And then, I've, coded using C++/CLI and .NET, my main user interface class, who does next:

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);

                ...
            }

}

The error is at line CP1626::setCallbackDataWriteFunc(dataWriteFunc); , and it says that a pointer to member is not valid for a managed class. What's the correct form to do this callback assignation when I'm on a managed class? I think that I should find a way to convert delegates into function pointers, but also I'm not sure about this.

Thank you in advance.

EDIT: I've tried to change line CP1626::setCallbackDataWriteFunc(dataWriteFunc); with CP1626::setCallbackDataWriteFunc(Marshal::GetFunctionPointerForDelegate(del)); , with dataWriteFunc^ del; a delegate with format delegate PNIO_IOXS dataWriteFunc(PNIO_UINT32 DevHndl, PNIO_DEV_ADDR * pAddr, PNIO_UINT32 BufLen, PNIO_UINT8 * pBuffer, PNIO_IOXS Iocs);

But it also fails. At this time, the error says 'CP1626::setCallbackDataWriteFunc : cannot convert parameter 1 from 'System::IntPtr' to 'PNIO_CBF_DATA_WRITE''

you might think about rereading part of the documentation from Microsoft. Even if it's old (like from 2006) it is not outdated.

Example. Microsoft documented the use of callbacks. https://msdn.microsoft.com/en-us/library/367eeye0.aspx

In your case, you didn't look, what GetFunctionPointerForDelegate() is returning. It is a IntPtr. This is a structure Microsoft uses to wrap all sort of pointers into one structure for .NET. It has the method void* ToPointer()

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

Be aware that you should use __stdcall for the callback. It is mentioned to be needed for compatibility.

typedef PNIO_IOXS (__stdcall *PNIO_CBF_DATA_WRITE)

If you are not able to recompile the sources to use __stdcall, just reroute it over another function you have defined.

I tried to use your code within a test project but i didn't want to setup to call the callback somewhere independent.

Kind Regards

ps I wanted to mark your question with low quality. Because there is documentation to read/google and learn from. You should take your time and be so kind to mark some of the answers for your four questions lately as the right answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM