How to marshal function with out parameter to native code? - c#

I have delegate that is declared as:
internal delegate bool readDelegate(out byte data);
At some point i want to get a function pointer to an instance of the delegate:
readDelegate reader = (out byte data) =>
{
Console.WriteLine("Managed output! opening");
if (stream.CanRead)
{
data = (byte)stream.ReadByte();
return true;
}
else
{
data = 0;
return false;
}
};
which reads a singy byte from stream, if able.
But when i try to get a function pointer, like this:
IntPtr foo = Marshal.GetFunctionPointerForDelegate(reader);
I get an exception:
System.NotSupportedException was unhandled
Message="0x80131515"
StackTrace:
в System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(Delegate d)
...
What is the reason? How should i change my code?

What's the rest of the message of the exception? There should be a explanation of the error.
Anyway, I think this might work:
internal unsafe delegate bool readDelegate(byte* data);

Related

void ** handles with P/Invoke

I am using a C API DLL from a 3rd party vendor. The problem I have is that I can't seem to find a good template for Marshalling the following C code:
API_Open( void ** handle );
API_Close( void * handle );
The calls are simplified, but the handle is a void *, which is (in C) passed into the API_Open call as &handle, and then passed into API_Close as handle.
I've tried to do the same in C#, but can't figure out how to Marshal handle properly. My C# version (latest try) is:
[DllImport("External.dll",EntryPoint="API_Open")]
public static extern int API_Open( out IntPtr handle );
[DllImport("External.dll",EntryPoint="API_Close")]
public static extern int API_Close( IntPtr handle );
public static int Wrapper_API_Open( ref Int32 handle )
{
int rc = SUCCESS;
// Get a 32bit region to act as our void**
IntPtr voidptrptr = Marshal.AllocHGlobal(sizeof(Int32));
// Call our function.
rc = API_Open(out voidptrptr);
// In theory, the value that voidptrptr points to should be the
// RAM address of our handle.
handle = Marshal.ReadInt32( Marshal.ReadIntPtr(voidptrptr) );
return rc;
}
public static int Wrapper_API_Close(ref Int32 handle)
{
int rc = SUCCESS;
// Get a 32bit region to act as our void *
IntPtr voidptr = Marshal.AllocHGlobal(sizeof(Int32));
// Write the handle into it.
Marshal.WriteInt32(voidptr,handle);
// Call our function.
rc = API_Close(voidptr);
return rc;
}
public void SomeRandomDrivingFunction()
{
.
.
.
Int32 handle;
Wrapper_API_Open( ref handle );
.
.
.
Wrapper_API_Close( ref handle );
.
.
.
}
The API return code is always INVALID_DEVICE_OBJECT when I call API_Close. Any thoughts? I thought this would be pretty straightforward, but I'm having trouble wrapping my head around the void** and void* parts of the function calls.
Thanks
You seem to be over-complicating this significantly. I don't know why you want to introduce Int32 for the handles since they do need to be pointer sized. You should use IntPtr.
The API_Open accepts the address of the variable where the handle is returned. The caller allocates that variable and passes it to the callee, which populates the variable. The C function might look like this:
int API_Open(void **handle)
{
*handle = InternalCreateHandle();
return CODE_SUCCESS;
}
You'd call that in C like this:
void *handle;
int retval = API_Open(&handle);
if (retval != CODE_SUCCESS)
// handle error
// go one and use handle
Translated to C#, the void* maps to IntPtr, and the use of the double pointer is just a means to get around the fact that C only supports pass-by-value. In C# you would use pass-by-reference.
For API_Close it is even simpler because we are passing the handle by value:
int API_Close(void *handle)
{
InternalCloseHandle(handle);
return CODE_SUCCESS;
}
And the calling code is simply:
int retval = API_Close(handle);
if (retval != CODE_SUCCESS)
// handle error
So, the C# wrapper functions should be:
public static int Wrapper_API_Open(out IntPtr handle)
{
return API_Open(out handle);
}
public static int Wrapper_API_Close(IntPtr handle)
{
return API_Close(handle);
}
At which point these wrapper methods do look somewhat pointless!

Exception when calling C++ function from managed code

Let's imagine C++ function in DLL:
typedef struct
{
int number;
void *list;
} clist_t;
extern "C" DLL_API clist_t GetItems(int a);
DLL_API clist_t GetItems(int a)
{
static clist_t list;
list.number = a;
list.list = sth();
return list;
}
And the C# code which calls this function:
[StructLayout(LayoutKind.Sequential)]
public struct CList
{
public int number;
public IntPtr ptr;
};
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate CList GetItemsDelegate(int a);
int func = Win32APIWrapper.GetProcAddress(m_dllHndl, "GetItems");
private GetItemsDelegate GeItemsFunc =
(GetItmsDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)func, typeof(GetItemsDelegate));
CList list = GetItemsFunc(12); // <--- here we got exception
The last function throws exception: "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
I noticed that removing second field in CList function causes exception to disappear and returned struct has correct value of number field.
So why the original code does not work? The alignment of structures seems to be correct. Also calling convention is properly set to cdecl.
Any ideas? Both types in struct are blittable, so there is no need to even marshal them (C# and dll are compiled to 32bit).
EDIT:
Why returning smaller struct does not throw exception? I noticed that struct smaller then 4 bytes are returned ok. On the other hand the same function but without parameters allows returning the original struct without exception.

invoke with multiple arguments resulting in FormatException

I'm trying to invoke a Form method from a different thread. In the form class, I have:
delegate int ReplaceMessageCallback(string msg, int key);
public int ReplaceMessage(string msg, int key)
{
if (this.InvokeRequired)
{
ReplaceMessageCallback amc = new ReplaceMessageCallback(ReplaceMessage);
object[] o = new object[] { msg, key };
return (int)this.Invoke(amc, o);
}
bool found = false;
int rv;
lock (this)
{
if (key != 0)
{
found = RemoveMessage(key);
}
if (found)
{
rv = AddMessage(msg, key);
}
else
{
rv = AddMessage(msg);
}
}
MainForm.EventLogInstance.WriteEntry((found)
? EventLogEntryType.Information
: EventLogEntryType.Warning,
IntEventLogIdent.MessageFormReplace1,
String.Format("MessageForm::ReplaceMessage(({2},{0}) returns {1}.\n\n(The message {3} exist to be replaced.)",
key,
rv,
msg,
(found)
? "did"
: "did not"));
return rv;
}
When I run this, I get an exception "FormatException was unhandled" "Index (zero based) must be greater than or equal to zero and less than the size of the argument list." on the call to Invoke.
Essentially this same code fragment works fine on class methods that only take a single parameter, so I assume I'm doing something wrong with the object array but I have no idea what.
An easier way to handle this is:
if (this.InvokeRequired)
{
int rslt;
this.Invoke((MethodInvoker) delegate
{
rslt = ReplaceMessage(msg, key);
}
return rslt;
}
It turns out that the invoke call will pass along exceptions within the function it calls, and you can't step (F11 in debugger) into it. I assumed that it would step into the called code, so when it failed I thought it was the actual Invoke call.
I messed up a String.Format in the body of the function, and Invoke passed that exception to me with no indication of where in the code the problem actually happened.

Marshalling a char** in C#

I am interfacing with code that takes a char** (that is, a pointer to a string):
int DoSomething(Whatever* handle, char** error);
Basically, it takes a handle to its state, and if something goes wrong, it returns an error code and optionally an error message (the memory is allocated externally and freed with a second function. That part I've figued out :) ).
I, however, am unsure how to handle in in C#. What I have currently:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern int DoSomething(IntPtr handle, byte** error);
public static unsafe int DoSomething(IntPtr handle, out string error) {
byte* buff;
int ret = DoSomething(handle, &buff);
if(buff != 0) {
// ???
} else {
error = "";
}
return ret;
}
I've poked around, but I can't figure out how to turn that into a byte[], suitable for feeding to UTF8Encoding.UTF8.GetString()
Am I on the right track?
EDIT: To make more explicit, the library function allocates memory, which must be freed by calling another library function. If a solution does not leave me with a pointer I can free, the solution is unacceptable.
Bonus question: As implied above, this library uses UTF-8 for its strings. Do I need to do anything special in my P/Invokes, or just use string for normal const char* parameters?
You should just be able to use a ref string and have the runtime default marshaller take care of this conversion for you. You can hint the char width on the parameter with [MarshalAs(UnmanagedType.LPStr)] to make sure that you are using 8-bit characters.
Since you have a special deallocation method to call, you'll need to keep the pointer, like you've already shown in your question's example.
Here's how I'd write it:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern int DoSomething(
MySafeHandle handle, void** error); // byte** should work, too, I'm just lazy
Then you can get a string:
var errorMsg = Marshal.PtrToStringAnsi(new IntPtr(*error));
And cleanup:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int FreeMyMemory(IntPtr h);
// ...
FreeMyMemory(new IntPtr(error));
And now we have the marshalled error, so just return it.
return errorMsg;
Also note the MySafeHandle type, which would inherit from System.Runtime.InteropServices.SafeHandle. While not strictly needed (you can use IntPtr), it gives you a better handle management when interoping with native code. Read about it here: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx.
For reference, here is code that compiles (but, not tested yet, working on that next tested, works 100%) that does what I need. If anyone can do better, that's what I'm after :D
public static unsafe int DoSomething(IntPtr handle, out string error) {
byte* buff;
int ret = DoSomething(handle, &buff);
if(buff != null) {
int i = 0;
//count the number of bytes in the error message
while (buff[++i] != 0) ;
//allocate a managed array to store the data
byte[] tmp = new byte[i];
//(Marshal only works with IntPtrs)
IntPtr errPtr = new IntPtr(buff);
//copy the unmanaged array over
Marshal.Copy(buff, tmp, 0, i);
//get the string from the managed array
error = UTF8Encoding.UTF8.GetString(buff);
//free the unmanaged array
//omitted, since it's not important
//take a shot of whiskey
} else {
error = "";
}
return ret;
}
Edit: fixed the logic in the while loop, it had an off by one error.

Invalid Variant crash

I have a situation where I've wrapped a Native C++ DLL with C++/CLI for eventual use in C#.
There are a few callback functions that are causing some issues at run time. Particularly, I get the following exception:
An unhandled exception of type
'System.Runtime.InteropServices.InvalidOleVariantTypeException'
occurred in ToadWrapTest.dll
Additional information: Specified OLE
variant is invalid.
On this line of code (C++/CLI):
public delegate int ManagedCallbackFunction (Object^ inst, const Object^ data);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
ManagedCallbackFunction^ m_callbackFn;
int intermidiaryCallback(void * pInstance, const void * pData)
{
void* temp = (void*)pData;
System::IntPtr ip1 = IntPtr(pInstance);
System::IntPtr ip2 = IntPtr(temp);
Object^ oInst = Marshal::GetObjectForNativeVariant(ip1);
Object^ oData = Marshal::GetObjectForNativeVariant(ip2);
//invoke the callback to c#
//return m_callbackFn::Invoke(oInst, oData);
return 0;
};
The reason I've made this "intermediary callback" was an attempt to circumvent the Invalid variant exception being thrown when I tried to directly map the delegate from C# to the native C++ code. As an attempted work-around, I declare a delegate on the C# side and pass that funcptr to the C++/CLI wrapper. I then pass the intermediary funcptr to the native C++ and just daisy chain the calls together.
What I know is that it all works in native C++ world. The problem is mapping the void* to the managed world. The following code shows the native C++ version of the callback:
int (*CallbackFunction) (void *inst, const void *data);
If anyone can help here, I'd really appreciate it.
Are pInstance and pData really VARIANT? If they are, I would expect your callback function to be more strongly typed:
int (*CallbackFunction)(VARIANT *inst, VARIANT *data);
If that's the case, in your code you should be able to look at the actual VARIANT to hand check it. If you are not really getting VARIANTs (ie, you are really just getting void * pointers), you shouldn't try to turn them into C# objects since there is no inherent meaning to them. They should get passed through as IntPtr. If you know that they should have some other type of inherent meaning, you need to marshal them as appropriate types.
Big Thanks to plinth on this one! I am posting the final solution below to anyone else who has to deal with 3rd party fun like this one! Please feel free to critique, as I am not done optimizing the code. This may still be to roundabout a solution.
First, the callback functions became:
public delegate int ManagedCallbackFunction (IntPtr oInst, IntPtr oData);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
ManagedCallbackFunction^ m_callbackFn;
Big props on this one. It just plain won't work if you try to cast from void* directly to Object^. Using the IntPtr and my intermediary callback:
int intermidiaryCallback(void * pInstance, const void * pData)
{
void* temp = (void*)pData;
return m_callbackFn->Invoke(IntPtr(pInstance), IntPtr(temp));
};
We finally get a working model on the C# side with some massaging of the objects:
public static int hReceiveTestMessage(IntPtr pInstance, IntPtr pData)
{
// provide object context for static member function
helloworld2 hw = (helloworld2)GCHandle.FromIntPtr(pInstance).Target;
if (hw == null || pData == null)
{
Console.WriteLine("hReceiveTestMessage received NULL data or instance pointer\n");
return 0;
}
// populate message with received data
IntPtr ip2 = GCHandle.ToIntPtr(GCHandle.Alloc(new DataPacketWrap(pData)));
DataPacketWrap dpw = (DataPacketWrap)GCHandle.FromIntPtr(ip2).Target;
uint retval = hw.m_testData.load_dataSets(ref dpw);
// display message contents
hw.displayTestData();
return 1;
}
I mention "massaging" the objects because the delegate is not specific to this callback function and I don't know what object pData will be until run time(from the delegates POV). Because of this issue, I have to do some extra work with the pData object. I basically had to overload the constructor in my wrapper to accept an IntPtr. Code is provided for full "clarity":
DataPacketWrap (IntPtr dp)
{
DataPacket* pdp = (DataPacket*)(dp.ToPointer());
m_NativeDataPacket = pdp;
};

Categories

Resources