Waze for WP7 – Deep dive into Cibyl

On my last post I introduced Cibyl as the tool I’m going to use for converting Waze to C#. Before talking about C#, let’s first learn how Cibyl converts C/C++ code to Java.

Let’s take the following simple program and see the list of actions one should do in order to convert it to fully running Java:

Original code

#include <stdio.h>

int main(int argc, char **argv)
{
  printf("hello");
  return 0;
}

 

Altered Code to comply with Cibyl:

#include <stdio.h>
#include <cibyl.h>

int main(int argc, char **argv)
{
  printf("hello");
  return 0;
}

The only line added was #include <cibyl.h>. What’s that?

Well, cibyl.h contains macros to replace every LIBC* (or MSVCRT if you want) function with Java byte code method with the same functionality. In this case printf will be replaced during pre-processing phase into 10K Java bytecode lines (I shit you not) that impement the entire functionality of, well, printf (parse the format params, add leading spaces etc.). Finally there will be a call from within the bytecode to Java code that implements writing character to the screen (the real I/O will always be implemented in Java so you can easily replace the implementation with your own one).

So if the input is main.c the output will be 2 files: Cibyl.j and Syscalls.java. Cibyl.j is a java bytecode file that contains the main and printf implementation in JVM bytecode commands. printf implementation contains the following call to Java code:

invokestatic Syscalls/NOPH_OutputStream_write(II)V

Syscalls.Java will contain the implementation of NOPH_OutputStream_write that simply outputs a character to the screen. Don’t worry about the (II)V notation, i will explain those later.

Both Cibyl.j and Syscalls.java are being compiled into corresponding class files and can be packaged in one Jar ready for execution. j files are JVM assembly files in Jasmin format ready to be compiled to class files. Read more about Jasmin in the link above.

Got you, what about real world code?

Real word code will contain calls to external libraries that implement drawing graphics, printing and all other I/O related functionality. I assume you already have this code contained in special directory in order to support multiple platforms (e.g. drawing pixels in iPhone is different than Android). So you need to add new directory for Java that will contain the same C/C++ code but all the external calls will be replaced with NOPH_<syscall>.

OK, you created new directory, added all C/C++ files and replaced every call with NOPH_ prefix. What’s next?

Since Simon (author of Cibyl) only provided replacement for LIB* functionality, you need to provide the Java functionality for any non-libc functionality you use. For example: if your code contains call to DrawPixel that was implemented in C by 3rd party library, now you will have to:

1. Replace the call to DrawPixel with a call to NOPH_DrawPixel.

2. Provide NOPH_DrawPixel Java code that implements the same functionality.

3. Tell Cibyl to connect 1+2.

When you execute Cibyl on your new code, Cibyl will identify each NOPH_ call and replace it with a call to your Java function that implements the NOPH_ call your provided in (2).

Well, how do i ‘tell’ Cibyl to connect 1+2?

Cibyl created syscalls directory under which there are implementation for LIBC system calls. You need to add new directory under Syscalls that will contain your specific Java functionality. This is splitted into 2 major parts:

1. Create Syscalls\MySyscalls\include directory. This directory will contain H files that contain the C prototypes of the system calls you’re about to implement in Java. For example:


typedef int NOPH_SoundMgr_t;

int NOPH_SoundMgr_listCreate(NOPH_SoundMgr_t sm, int flags);

2. Create Syscalls\MySyscalls\classes\SoundMgr.java that will contain:


public int listCreate(int flags) {

/* some code */

}

3. Run `cibyl-generate-c-header -o Syscalls/ sound_mgr`. This will create cibyl.h file that contains macro definition named ‘listCreate’ that order the JVM bytecode to call Java function named listCreate.

H file containing prototypes for Java methods, you must be kidding

There must be a way for your original C/C++ code to communicate with the new Java functionality. In order to achieve that, you define prototypes using the C builtin data types. These types have correspong types in Java so this is the way both language communicate. Similarily to Win32, most of the time you create objects in Java and return HANDLE (int) to the C/C++ code for further calls. In the example above NOPH_SoundMgr_t is such a handle that will represent the sound manager for both C/C++ and Java code. All other objects can be represented in similar way.

On my next post I will explain the conversion of Cibyl from yielding Java code into .NET code.

Advertisements
This entry was posted in Waze, WP7 and tagged . Bookmark the permalink.

One Response to Waze for WP7 – Deep dive into Cibyl

  1. Pingback: Waze for WP7 – the journey begins | Meir Tsvi's blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s