Walking the roads of madnessPosted: March 27, 2012
Well, it started innocently enough. I wanted to add some very fast core networking interop to my code. So, I started with the Winsock library on Windows because I want to use I/O completion ports. Alright, fair enough, and an easy job was made of doing basic Berkeley style network socket calls. Then along came some nefarious data structures, notably, WSAPROTOCOL_INFO. Buried within that data structure is the innocent GUID.
Well, of course implementing GUID didn’t lead directly down the path of COM, but it was so innocently close I could not resist. So, down the COM rabbit hole I went.
COM is a very ancient technology. It was invented in the early days of Microsoft wanting to embed components such as pictures, spreadsheets and the like into Word documents. It was such a great idea, that over the past 20 years or so, the world has had the benefit of living the glory of a COM existance through Windows.
COM is many things. It is a type system, a runtime, a programming way of life. There are tons of interfaces, functions, and the like. There’s stuff for “server” side, and “client” side, proxies, asynchronous stuff. The list goes on and on. There are type libraries, which sometimes lie, and AddRef/Release for “garbage collection”. There are BSTRs, Variants, SafeArray, and a whole host of other data types, conversions between the data types, and on and on it goes.
If all you want is access to your Kinect though, what to do?
You can start off easily enough:
sensor = CreateObject(IID_INuiSensor);
Once you have a handle on the sensor, you can make some calls.
imageStream = sensor.NuiImageStreamOpen(...)
sensor.NuiImageStreamGetNextFrame(imageStream, 30, imageFrame)
Then go and do something with the frame. This isn’t exactly the code you would write, but it’s pretty close to what will be there eventually.
To make stuff work in COM, there’s a lot of work that has to be done with interfaces. It’s just like any other code, you have to define the various structures and method definitions. In some cases, you might have what’s known as a type library (.tlb) file, which is a binary encapsulation of the interface to the objects. In most cases though, all you have is a header file with all the GUID and interface goop laid out in barely readable form.
For the first few cases, I am hand coding the interfaces from header files. A better approach long term will be to use the MIDL compiler to create a .tlb file, then read the .tlb file to get all the type and method information. Once I can do that, I can construct the definitions from their source and ditch the hand transcription.
There is another possibility that occurs to me though. Rather than constructing a bunch of code that mimics all the interfaces known to man, since Lua is much more dynamic, interfaces can be constructed on the fly. If I have the .tlb files for something, then I can read it at runtime, and using the __call() metamethod, just call the appropriate method when the user makes the call. Basically, I could construct the appropriate ffi.cdef[] construct, then make the call, as long as the library has already been loaded into memory.
If that technique works, it would be the bees knees. No need to generate large amounts of code, just ship the .tlb files, and leave it at that.
At any rate, dealing with “legacy” coding paradigms can be a real pain some times. The benefit is getting access to a bunch of stuff, which can then be incorporated with new code and paradigms.