Escobar
asked on
C# callback handler and type conversions
I have an API (I have control over it) written in C that accepts a callback target. During execution, the API will call back presenting an event code and a void * for the event context. Its the basic WndProc model (where the LPARAM will be cast'ed to the appropriate struct pointer), where depending on the event the context is converted to a pointer to a structure specific to that event.
In C#, the callback works, thats simple. What doesnt work is my efforts to on event X, convert the void * context argument to a C# structure.
How do I get the generic void * argument converted to a C# struct of type X for an event type of X, and a type of Y for event type Y?
I can of course take the brute force method of setting multiple callback targets, one for each event type, where the callback context is a known structure type, but thats less than ideal. Then again, its a small set of events, so maybe ill go that way. Regardless, this is something id like to understand going forward.
Im hoping this is a function of the language (C#) that I do net understand fully, so ive listed this as 'easy'.
Thanks
In C#, the callback works, thats simple. What doesnt work is my efforts to on event X, convert the void * context argument to a C# structure.
How do I get the generic void * argument converted to a C# struct of type X for an event type of X, and a type of Y for event type Y?
I can of course take the brute force method of setting multiple callback targets, one for each event type, where the callback context is a known structure type, but thats less than ideal. Then again, its a small set of events, so maybe ill go that way. Regardless, this is something id like to understand going forward.
Im hoping this is a function of the language (C#) that I do net understand fully, so ive listed this as 'easy'.
Thanks
ASKER
Code, if my question was not clear...
C API
extern "C"
{
// Define the signature for a callback event handler
typedef unsigned int (CALLBACK * EGLEVENTTARGETPROC)(unsign ed int eventId, void * context);
}
EGLAPIEXPORT bool eglApplicationStart(EGLEVE NTTARGETPR OC eventTarget);
typedef struct tagEVENT_DUMMY
{
unsigned int test;
} EVENT_DUMMY, * PEVENT_DUMMY;
C# client
[StructLayout(LayoutKind.S equential, CharSet=CharSet.Unicode)]
public struct EventDummy
{
public uint test;
}
public delegate uint _EventHandler(uint eventId, [MarshalAs(UnmanagedType.S ysInt)] IntPtr context);
public static uint eventHandler(uint eventId, IntPtr context)
{
switch (eventId)
{
case 0: // Dummy EVent
{
// Now, how do I get the context in to a usable EventDummy structure?
}
break;
}
return (0);
}
C API
extern "C"
{
// Define the signature for a callback event handler
typedef unsigned int (CALLBACK * EGLEVENTTARGETPROC)(unsign
}
EGLAPIEXPORT bool eglApplicationStart(EGLEVE
typedef struct tagEVENT_DUMMY
{
unsigned int test;
} EVENT_DUMMY, * PEVENT_DUMMY;
C# client
[StructLayout(LayoutKind.S
public struct EventDummy
{
public uint test;
}
public delegate uint _EventHandler(uint eventId, [MarshalAs(UnmanagedType.S
public static uint eventHandler(uint eventId, IntPtr context)
{
switch (eventId)
{
case 0: // Dummy EVent
{
// Now, how do I get the context in to a usable EventDummy structure?
}
break;
}
return (0);
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Sometimes you just need to walk away for a few days. Your suggestion, while not technically correct, did help me to find the answer.
I understand the need for unsafe code marking, at the method and project level and that was already in place. At first, on reading your answer, I though that the problem may have been that I was not marking the structure definitions as unsafe. But the problem actually was that the structure in question, contains as a member, a managed type reference. The C api works with components that are also addressed by .NET classes. So the C API may return an object interface pointer that I can share with the .NET code. My mistake was listing the member of the struct as the .NET managed type and not as a generic intptr and performing a conversion later on in code. I was simply misreading the error as if it referred to my use of the structure itself, instead of in m use of n embedded managed type within an unmanaged or unsafe structure.
Thanks very much
I understand the need for unsafe code marking, at the method and project level and that was already in place. At first, on reading your answer, I though that the problem may have been that I was not marking the structure definitions as unsafe. But the problem actually was that the structure in question, contains as a member, a managed type reference. The C api works with components that are also addressed by .NET classes. So the C API may return an object interface pointer that I can share with the .NET code. My mistake was listing the member of the struct as the .NET managed type and not as a generic intptr and performing a conversion later on in code. I was simply misreading the error as if it referred to my use of the structure itself, instead of in m use of n embedded managed type within an unmanaged or unsafe structure.
Thanks very much
ASKER
C API
extern "C"
{
// Define the signature for a callback event handler
typedef unsigned int (CALLBACK * EGLEVENTTARGETPROC)(unsign
}
EGLAPIEXPORT bool eglApplicationStart(EGLEVE
typedef struct tagEVENT_DUMMY
{
unsigned int test;
} EVENT_DUMMY, * PEVENT_DUMMY;
C# client
[StructLayout(LayoutKind.S
public struct EventDummy
{
public uint test;
}
public delegate uint _EventHandler(uint eventId, [MarshalAs(UnmanagedType.S
public static uint eventHandler(uint eventId, IntPtr context)
{
switch (eventId)
{
case 0: // Dummy EVent
{
// Now, how do I get the context in to a usable EventDummy structure?
}
break;
}
return (0);
}