Tuesday, March 22, 2016

#include Woes

<< Prev: Loading Firmware       Next: Parsing Firmware >>

Is Apple somehow unaware that in order to use their lovely APIs, you have to #include them first? It makes the IDE (not to mention the compiler) a little cranky when you omit that part.

Yet, have a look at this documentation for OSKextRequestResource again. It says it's documenting OSKextLib.h, so you might try something like this:

#include <OSKextLib.h>

Nope. That header is itself in something, or under something. In or under what? No indication. Maybe Apple has some other documentation on how to use that? Perhaps under Creating a Device Driver with Xcode?

Well, that gives a code sample that actually includes a #include (yay!), but it's not the one we need here.

This kind of problem came up a number of times. I needed to use an OSData object to store the results ultimately generated by the OSKextResourceRequest. Let's look at the OSData Class Reference. That page doesn't even name the header file it's in.

There's also a detailed article on kernel data structures including OSData, with code samples, big and small. Neither the big ones nor the small ones include the #includes. As far as I can tell the article never mentions what to #include either. Maybe if you always write tidy, one-class drivers that do virtually nothing, it just works based on what a "heavyweight" header such as #include <IOKit/IOLib.h> ropes in, but that's not that helpful in general.

So, it comes down to the source code I guess. Googling OSKextRequestResource turns up this source code. From the URL, you might decide to try

#include <libkern/OSKextLib.h>
or
#include <libkern/libkern/OSKextLib.h>

That first one turns out to work.

There’s also the good-old-grep method:

cd /Applications/Xcode.app/Contents/Developer/
cd Platforms/MacOSX.platform/Developer/SDKs/
cd MacOSX10.11.sdk/System/Library/Frameworks/
grep -r "OSKextRequestResource" *

The output is a bit of a mess, but you'll find Kernel.framework/Headers/libkern/OSKextLib.h in there, suggesting the libkern/OSKextLib.h used above.

For what it's worth, OSData seems to be defined in libkern/c++/OSData.h (try searching for "class OSData" if you don’t want to be overwhelmed by occurrences of just "OSData"), though again it tends to get roped in by the IOLib imports such as IOService.h. I have to think there's some middlin' header that includes just the data structures like OSData and OSDictionary and stuff, but I haven't come across it yet.

Why is this so difficult?

It makes me think that one of the huge advantages of Java is the documentation. Which in turn, is build on the package system. If you look at HashMap, for instance, right above the big words Class HashMap are the little words java.util and immediately you know precisely the import you need to write to actually use this class.

Even supposing C/C++ isn't amenable to that level of automated quality documentation generation (though why should it not be?), Apple certainly had the opportunity in the articles like this one to make the needed #include clear.

Oh, well. Grep on.

<< Prev: Loading Firmware       Next: Parsing Firmware >>

No comments:

Post a Comment