How to call Framework functions defined inside of structs?

I'm a long-time .NET developer working on my first Xamarin Mac project. I'm trying to call into IOKit for some USB functionality, but I've run into some problems. I can scan through and retrieve information about connected devices by importing C functions and calling them like this:
[DllImport("IOKit.framework/IOKit", CharSet = CharSet.Ansi)] public static extern int IOServiceGetMatchingServices(IntPtr masterPort, IntPtr matching, out IntPtr iterator);
This "core" part of IOKit works great. However, once I have the device, I need to use the USB component of IOKit (I think it's called IOUSBLib) to perform the actual USB communication. Unfortunately, all the functions in this portion of the framework are contained in C structs. Here's the beginning of IOUSBDeviceStruct:
typedef struct IOUSBDeviceStruct { IUNKNOWN_C_GUTS; IOReturn (*CreateDeviceAsyncEventSource)(void *self, CFRunLoopSourceRef *source); CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *self); IOReturn (*CreateDeviceAsyncPort)(void *self, mach_port_t *port); }
How does one call into these structs? I tried to look through the docs, but most of the stuff seems to be focused on Objective-C libraries, which doesn't seem relevant (or is it? I'm a total novice with Mac development).

Side problem: I tried to look up the actual mangled method names to try to get the appropriate EntryPoint to pass to DllImport like I'd do on Windows with C++, but running:
nm -a /System/Library/Frameworks/IOKit.framework/IOKit
produced a large symbol table, but none of the IOUSBLib functions were contained in that. Any idea which library tool I should be using on OS X to view info about this stuff? Or are the IOUSBLib calls in some other spot?

Tagged:

Answers

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    So this is one of the reasons that Xamarin.Mac does't support IOKit currently. It's a total beast to bind.

    I believe you need to do the following:

    • Figure out the size of IUNKNOWN_C_GUTS so you can pad your c# struct to match the native side. Maybe jump to definition in xcode and dig?
    • Define a C# struct with a padding of that size, and then a number of delegates for each function pointers.
    • Make sure every function pointer you call EXACTLY matches the native side. If you mess this up, you will have fun crashes to debug.
    • Marshal.PtrToStructure your IntPtr to your C# matching struct.
    • Invoke the relevant delegate.
    • Cross your fingers.
  • DaveHuntDaveHunt USMember ✭✭✭✭✭

    It might be easier to create an Obj-C wrapper around IOKit that operates in a more C#-friendly fashion, then create a C# binding to that.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    That is a good idea Dave. Simple C APIs are much much more simple to bind.

Sign In or Register to comment.