I don’t like C#, but the free version of Visual Studio only lets you use the interface builder in C#/.net programs, so here we are. My goal was to cheat and write the interesting parts of the program in C/C++, compiling to a .dll, and calling it from C#.
This has turned out to be an ordeal.
I have a great handle on calling functions in a .dll from Python. The CTypes module is amazing, and incredibly well documented. C# has a module (service?) in the System.Runtime.InteropServices namespace and the Platform Invoke service for “consuming un-managed code”, but it has been a real pain getting it to work.
I’ll admit that 80% of the problem is that I’m still fairly new to C#, but there is no shortage of information online for vanilla C# programming. Interfacing to a .dll seems to be uncommon enough that it’s hard to find exactly what I’m looking for when I run into a use-case that hasn’t been discussed much.
Here’s what I’m getting at. Let’s say I have a function in my .dll as such:
INTEROPSTRUCTTEST_API int GetInteger() { return 42; }
Here’s what the function in C# would look like for interfacing with GetInteger() in the .dll (which I put in a class called InteropStructTestDLLWrapper):
[DllImport("InteropStructTest.dll")] public extern static int GetInteger();
And here’s how to call that in C#:
int int_from_dll = 0; int_from_dll = InteropStructTestDLLWrapper.GetInteger();
This behaves exactly as you would expect – it returns the number 42. Things start getting weird when pointers are involved.
Function in .dll:
INTEROPSTRUCTTEST_API void PassIntegerPointer(int *i) { *i = 27; }
Function for calling the .dll function in C#:
[DllImport(InteropStructTest.dll, CallingConvention = CallingConvention.Cdecl)] public extern static void PassIntegerPointer([In, Out]ref int i);
Calling the function in C#:
InteropStructTestDLLWrapper.PassIntegerPointer(ref int_from_dll);
Now you have to deal with [In, Out] and ref, and CallingConvention.Cdecl. Much of this was guess-and-check to get working using information I gleaned from dozens of StackOverflow posts and other blogs. Things start getting extra weird when you want to pass a pointer to a struct or array of structs.
I decided it was best to just start making a sample .dll and .cs program that demonstrated a clear use-case for passing various data types to and from a .dll. Something that I could reference and add to as I learn. So far it has returning integers, passing a pointer to integer to be modified, passing a pointer to a struct to be modified, and passing an array of structs to be modified (which was super hard to find anything online about).
https://github.com/cheydrick/CSInteropStructTest
Right now it has examples of all the things I’ll have to do in small side-project I’m working on. I’ll flesh it out as needed.
Hopefully I’ll save someone some time. I’m embarrassed at how much time I burned getting this far!