Just to mix things up a little, I thought I'd actually post a message in here.
Python and Ruby are languages that feature powerful OO semantics. Both languages are slower than compiled languages, however, and both of them work around this by making it easy to import and use binary libraries. Every time I think about writing a C library for Python or Ruby, however, I am struck by the fact that the libraries are inherently procedural
rather than object-oriented. Today I have been giving thought to the problem of making a C-style API act a little more OO.
So far about the best thing I can think of is a "handle" approach: a manual ctor/dtor/object* semantic. Imagine we have a class Foo that has integer count and string m_string members, and a method "bar" that returns a m_string duplicated m_count times.
CFoo* create_foo(const char *new_string="", int new_count=1);
void destroy_foo(CFoo *pThis);
void set_count(CFoo *pThis, int new_count);
int get_count(CFoo *pThis);
void set_string(CFoo *pThis, const char *new_string);
const char * get_string(CFoo *pThis);
const char* bar(void);
There are SO many problems with this approach; chief among them being that the library is leaving resource cleanup to the user. In fact, the library is completely detached from the garbage collector and other convenient subsystems that the scripting language might employ. We could write a gc() method and have the garbage collector call it, I suppose. Another common approach is to have init() and shutdown() methods; init could setup any precached objects or calculate lookup tables and the like, while shutdown() could garbage collect any outstanding objects.
The next option is to build a class in the scripting language that utilizes the library, and interact exclusively with that class.
def initialize(string="", count=1)
@foo_ptr = create_foo(string, count)
This method seems to be the only way to attach the library to the OO properties of the language but to my mind it seems like so much extra overhead. Especially if the library wasn't written to support OO in the first place. It's almost as if the library is designed to exist in a separate process, needing to clean up its own resources and handle everything on its own, but without any kind of clues from the compiler or OS about when to go about it.