Question

With the inability to go into to much detail, imagine the following situation:

You are developing a library that needs to run on various embedded platforms (AVR, ARM, etc..). Some functionality of said library needs some sort of time keeping (not an actual time but along the lines of "it is now x (mili)seconds later than the last time we were called).

When there is no operating system available, there's no guarantee that any function that can provide this functionality is implemented (not with a universal name, at least). What would be the best practice to provide this functionality?

  • Do I implement only the function header and require the application using the library to implement it?
  • Do I create an init routine to which a function pointer is passed?
  • Something else?

Thanks in advance.

Was it helpful?

Solution

I have used both of your suggested approaches in the path. For your timekeeping function, I would usually document it like this in the public header file:

/*!
 * Platform-specific time-keeping support for mylib.
 *
 * This is used internally by mylib for reasons X, Y, and Z.
 *
 * @return  The number of milliseconds since this function was last called.
 *          -1 will be returned on the first call.
 *
 * @note    The hosting application must implement this function and is
 *          responsible for ensuring any necessary platform-specific
 *          initialization has taken place.
 */
int32_t mylib_get_elapsed_time(void);

One thing to consider about this approach is that it may introduce some compile and/or link-time dependencies. If you want to distribute this library in object form, this may be undesirable. The approach of using an init function and requiring the client to pass a pointer to its version of mylib_get_elapsed_time during initialization may reduce or eliminate such issues. It may also be easier to ensure that platform-specific initialization is done before your library is used.

You may also consider creating/bundling versions of this function for major/common platforms that you target, with the ability for others to contribute back. For example, you might have a platforms directory in the source tree that can contain tested implementations of this function (and others like it that have platform-specific implementations).

OTHER TIPS

Well clearly some aspect about your library has to be dynamic, meaning its behavior is dependent on some external aspect, whether that be the name of a library to add or the name of a class to instantiate.

It really is only a question of what aspect of your will be dynamic.

I've run into this type of problem before using Java, and since Java is not platform specific, you could run it potentially on any operating system that supports Java. Of course not every functionality is available in every operating system, meaning you need to be able to intelligently adapt your program according to the operating system.

The approach I took was to use classpath as the dynamic external factor. According to the operating system present, it would include the main library (jar) as well as an additional library written specifically for that particular operating system in which it was installed (the batch file launching the program is almost certainly platform-specific anyway, so what better place to place this particular platform-specific change?). Java specifically has a handy ServiceLoader designed to allow other libraries to implement interfaces in your main jar.

Your main library can call them as an interface without knowing who or how it is implemented, and your add-on library can perform timing mechanisms if available. If no interface implementation is available, have a fallback mechanism for when timing mechanisms are not possible.

You may not be using Java, but this idea is relatively easy to extend to other languages with a bit of reflection. Use a parameter passed to the program as a name of the implementation class for your timing mechanism. If a parameter is passed, try to instantiate a new instance of it dynamically and you're set to go. Just be sure to include a reference to your external library when you launch your program.

You'll most certainly want to separate the main functionality from the plugin, but if done in this way, you could easily upgrade/extend the plugin without ever having to touch the main program.

Licensed under: CC-BY-SA with attribution
scroll top