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
p.s. 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.