Friday, January 17, 2014

Porting, the loss of the age!

Last few days I have been having a play round with porting GLFW to D. But why would I do this since its a C library?

For me the benefit of porting GLFW to D is more for entertainment than anything. It also means I get more familia with such a project. I am already aware enough to have made DOOGLE to its current point. But I feel its design isn't the best. Plus its not at all based on a stable code base.
My port is available at link.

So at this point I have monitor module completely ported (except its C interface). Still haven't done too much for window, context. They have the bare bones structure already outlined. Its just the matter of porting the code which handles it.
Now this is the hard part.

Porting complex scattered code bases. Or more formally known as a C/C++ code base.
So this is more what this blog post is about. How to tackle such a task. Its hard. I'm not an expert in the matter nor would I want to be.

First things I did see quite quickly while looking at the module breakage implementations is that there are platform specific apis e.g. win32_window.c. Now once getting into code.. Seeing stuff like this _glfwPlatform* makes me suddenly think heyyy heres the internal api. Awsome. Not only do you have the public api to port but some how make it work well with the private api!

So now the tasks increase significantly. From port some public c code to D to port the public api and hide the actual implementation based upon the platform ext.

For this task I went with grabbing the most complex and interconnected module (Window). Defining its public api, in my case refactoring it out into a class for good measure. While defining all the extern(C) declarations. But thats not the library ported so moving on. Now how about some way to implement it without actually doing versioning within methods? Registration base system. Essentially what I did with Cmsed's router/data models.
Okay so can now register/create/get implementations of a window. Next step next less complex task. But already defined a little bit. Monitors. They themselves are not really dependent on anything else. So they are easy to port in full.
The next module I ported was context's public api. That was easy.

From here there was another one or two modules that could be ported easily. At least in public api. So they were.
Unfortunately code like the window and context modules are so highly dependent on others they can't just be ported without everything else done first.

What I'm describing is:

  1. Get the most complex piece of code base interface designed and ported.
  2. Get any stragglers definitions ported. If possible port any code associated with it (if standalone).
  3. If possible go back to existing interfaces that have been ported and implement them if all dependencies are already done.
  4. By now all possible utility and standalone code has already been done.
    Basically repeat step 3 until its done. If a modules dependency depends on others. Just pick some functions and do them. You already know the interface and how to get access to any values for it.
  5. Clean up. Make sure everything is there both in public api and in private that is required.
These steps are based upon chiseling away at a the code base till you have a very refined and nice looking code. You always start large then make small changes and go back up as required.

Its just my opinion however. And what seems to work for me.

No comments:

Post a Comment