[GD-General] API design thought/PrefLib
Brought to you by:
vexxed72
From: Brian H. <ho...@py...> - 2003-12-16 04:42:53
|
One of the problems typically encountered when trying to design a portable library's API is dealing with platform specific flags/parameters. Examples: - specifying choice of DX or OpenGL under Windows (moot under Linux and OS X) - choice of OpenGL32.DLL - specifying preference for DD 5.1 vs. stereo sound - selecting IRDA vs. TCP/IP for sockets on a PocketPC There are at least two standard ways of handling this that I'm aware of. The first is to simply have a ton of flags that are known to be system specific, e.g. you have a PREFER_OPENGL flag which is ignored on everything but Windows: MyLib_init( ..., SOME_FLAGS | PREFER_OPENGL ); The second way is to have "backdoor" functions that are only available on a specific platform, so possibly requiring an #ifdef: #ifdef _WIN32 MyLib_setOpenGLLibrary( "opengl32.dll" ); #endif I've never liked these, because they pollute all namespaces for the sake of a hack on a small subset of platforms. Then I remembered the cvar system in the Quakes. I always thought of them as borderline hackery, but in hindsight they're actually elegant in their ability to broadcast huge amounts of information, dynamically (editable at console) but in a fashion that only the interested subsystems will care about. You can set "gl_finish 1" and it has no effect, unless you're running the GL renderer. So instead of polluting/hacking an API in order to deal with each platform's little quirks, it seems that it would be better to use a cvar system to broadcast all non-portable or dynamic information. What I've done is made a simple properties system, which I'm sure everyone else has done as well. Then for a particular API, you simply pass it the property system and it uses that for any private crap it needs. property_system *ps; PropLib_createPropertySystem( &ps ); PropLib_setPropertyString( ps, "opengl DLL", "opengl32.dll" ); . . . MyLib_initOpenGL( ... /* misc stuff */, ps ); You can then dump all your This does introduce a dependency on a new library, the property_system stuff, but it seems to have a lot of other benefits going for it if you're developing a lot of portable libs. This ties into the PrefLib as well, since I was having a hard time reconciling PrefLib's persistency vs. performance expectations (i.e. does it cache then write on flush, or does it always write-on-modify, etc.). So now PrefLib is WAY smaller, because it doesn't have its own property system. Instead, you simply create your properties using PropLib, then you can serialize however/whenever you want: PrefLib_createPreferences( &pf, "com.pyrogon.mynewgame" ); PrefLib_writeProperties( pf, ps ); The PrefLib ONLY takes care of reading/writing to the platform specific preferences facilities (although at this point I'm just preferring file system preferences and only going to the registry when requested), and it doesn't handle property management at all. It's a clean break between the two, which is probably what I should have done originally. And more importantly, I've solved a problem for my other to-be-open-sourced stuff with how they deal with platform configuration options. Does this all sound sane? Brian |