Thursday, 5 March 2009

C# interop

C# interop with unmanaged code is not nearly as difficult in practice as it sounds on paper. Most of the interop I have done has been COM (to/from managed code) but for my current freelance gig I need to call from C# into an ANSI C DLL.

I wrote a few simple ANSI C functions to act as the interface to my managed code, just to save some work. I could call them fine. Crucially, I could pass in ANSI strings and get them back.

Then I started getting an AccessViolationException "Attempted to read or write protected memory". I was positive that I had annotated the ANSI C code correctly to export the functions. The C# code had the appropriate DllImport decorations. C# and ANSI C thought the function was CDECL. Everything looked just fine.

The symptoms were downright peculiar. If I declared a local variable in the ANSI C function that I was calling the code threw the exception. If I attempted to call another function from inside the ANSI C function the code threw the exception.

As with so many things, it boiled down to an incorrect setting in the project file, a residual glitch from the fact that I first produced an EXE to exercise the code and then flipped to producing a DLL.

Along the way I learned that I don't need to mess about with IntPtr allocation and freeing. When I have a mutable string (e.g. the result is returned in a char* parameter), I can create a StringBuilder with the appropriate size and pass that from C#. C# marshals it for me.

No comments: