Wednesday, January 23, 2008

Really, really nice

Just a quick one today.

After my previous qemu post, I found this really cool article on how to debug the linux kernel itself running on the emulator. It even uses Eclipse CDT so you have a nice IDE while debugging the kernel code.

Great stuff...

Tuesday, January 22, 2008

Fork/exec while redirecting I/O

Here's a common problem in (POSIX) C applications: let's say you want to execute another application, but you want to redirect this application's standard I/O (i.e., stdin, stdout, stderr) to a file descriptor(s) of your choice. Perhaps you want to log the output to a file, or stream the application's input from a file you just created, or collect error messages (stderr) for parsing later.

The function below illustrates how to do this:

pid_t
exec_redirect(
const char *path, char *const args[],
int new_in, int new_out, int new_err
)
{

pid_t child;

// Fork new process
child = fork();

if (child == 0) {

// Child process

// Redirect standard input
if (new_in >= 0) {
close(STDIN_FILENO);
dup2(new_in, STDIN_FILENO);
}

// Redirect standard output
if (new_out >= 0) {
close(STDOUT_FILENO);
dup2(new_out, STDOUT_FILENO);
}

// Redirect standard error
if (new_err >= 0) {
close(STDERR_FILENO);
dup2(new_err, STDERR_FILENO);
}

// Execute the command
execv(path, args);
}

// Parent process
return child;

}

This function takes the parameters path and args which is the same as what you would normally pass to execv(3). In addition, there are three parameters, new_in, new_out, and new_err which are (optional) file descriptors where the new application's standard input, output, and error, respectively, will be redirected from/to. To make redirection optional, we specify that if the descriptor parameter is -1, then no redirection will take place.

So how do we use this? The code snippet below executes the command line /bin/myapp -l -p, with input redirected from in.txt, output redirected to out.txt, and error redirected to err.txt:

    ...
char *cmd = "/bin/myapp";
char *args[] = { "/bin/myapp", "-l", "-p", NULL };

in = open("in.txt", O_RDONLY);
out = open("out.txt", O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
err = open("err.txt", O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);

exec_redirect(cmd, args, in, out, err);
...

On a closing note, it's also probably a good idea to close() the file handles in the parent process, after exec_redirect(), just to prevent "inadvertently" accessing them while the child process is also doing the same. Yes, the pun was intended ;-)

[Update: fixed some typos]

Thursday, January 17, 2008

A Quick Eclipse-based XML Editor Using EMF, Part I

Introduction

I've recently been dabbling in OSGi technology and found DS (Declarative Services) feature neat for automagically registering and finding/consuming services. Basically, instead of having to call OSGi APIs for registering Java objects(services), you will just need to "declare" these provided services in an XML file and the DS framework will take care of registering it for you. Similarly, if your application needs a service, instead of finding (and tracking) it yourself in code, just declare it in the XML file and DS will take care of "injecting" it into your object and tracking dynamic registration/unregistration. It is very reminiscent of Spring Dependency Injection and in fact, Spring has a very similar technology called Spring DM (Dynamic Modules). In the end, these technologies are all about decoupling your business logic from framework/container (e.g.OSGi) APIs, which promotes greater code reusability.

Anyway, like I said, the configuration is XML-based and being the lazy (in a good way ;-)) developer that I am, I wanted an integrated editor in Eclipse to edit these DS files. Nowadays, whenever I see and XML<->Java binding (plus Eclipse integration) problem my neurons automatically fire "EMF!", and so I set about trying to use this technology to create my own editor.

Which brings us to our first box-looking thingie:

What is EMF?

  1. A (meta-)modeling language (ecore)
  2. A Java code generator for your model
  3. An (extensible) XML<->Java binding framework

In addition to the above, you also get the following:
  • Reflective API (e.g., eGet("sandwich") method in addition to getSandwich() method)
  • Change notification
  • Base adapter & adapter factory classes for most model editing needs (providing content, labels, etc. for your model)
  • Command-based editing, undo/redo support
  • A sample Eclipse editor which you can customize or study
  • An option to export the editor as a standalone RCP app (cool!)


As a modeling technology, EMF is pretty solid and feature-rich. However, for this case, we don't need to create models because there is already a schema available - it's in the OSGi specs. EMF already has the ability to convert any XSD schema to an ecore model, and vice-versa.

The DS schema looks something like this:


I just copied it from the specs and saved it to a file in my system.

Here, then, is the quick procedure for creating the editor. Are you ready? Don't blink your eyes because this will be F-A-S-T! :-)

1. From Eclipse, click New->Other..., then select EMF Project as below:


You will be prompted for a project name. Type, e.g., org.example.ds.

2. Select a Model Importer. For now we use XML Schema:


Then, browse to where you saved the DS schema file (.xsd).



3. In the next page you will be asked what packages to import. EMF tries to generate a model filename from the schema contents but it's sometimes not nice (e.g. _0.ecore). You can rename it if you want, like here I renamed it to ds.ecore.


4. When the wizard is finished, you will have a new project in your workspace, with the generated ecore model (ds.ecore). Also, there will be a ds.genmodel file which is a generator model for your model: it tells EMF about code-generator-specific stuff like where to put the generated files, what base package name to use, etc.

You can view and edit these files via the Ecore and GenModel editors already bundled with EMF:



Again, the package name derived from the schema might not look nice ("_0"), so here we can rename it. In the Ecore editor, select the package _0, and in the Properties View, set the Name property to "ds".


5. Now that that's out of the way, we can configure the code generator. First, double-click the ds.genmodel file. It will open the GenModel editor:


We can set the Base Package property to org.example so that the generated package will start with org.example.ds. And also rename the Prefix property to "Ds" (previously it was "_0").

6. Code generation time!

Select the root genmodel (Ds), right-click, then click the Generate Model Code, Generate Edit Code, and Generate Editor Code commands successively.


If successful, it will generate the Java code for your model, as well as 2 new projects: a UI-agnostic .edit project which you can re-use outside of the Eclipse environment, and an Eclipse-specific .editor project which is tightly bound to (you guessed it) the Eclipse environment.

The editor application is complete!

7. You can test it by launching a new Eclipse instance from the workbench:


It will run a new Eclipse environment with your core, edit, and editor plug-ins included. In it you can try to create a new DS file via New->Other...->Example EMF Model Creation Wizards->Ds Model.


If you try to double-click this new file, it will invoke the .editor plugin you just created, and show a nice tree-based editor for you!


The great thing is, if you try to look at My.ds using a text editor, you will see the underlying data is fully compliant XML!


What's Next

We've gone from zero (editing XML by hand) to hero (editing the same XML by a neat, integrated, GUI-based editor) in just a few mouse clicks. But that is not all that EMF can do! I just hope this article has gotten you interested enough to want to have a deeper look. :-)

From here, where can our DS Editor application go? Well, I can see a few things for improvement already:

1. The generated class names are ugly!

Did you have a look at the generated model/Java code? There are classes whose names are Tservice, Tproperties, and so on (fugly!). These are a direct consequence of the <complexType name="xxx"> declarations in the schema. It would be nice if the generated class names were more, hmm... how you say... Java-ish? :-p Like Service and Properties, respectively, for example.

In the next parts I will show how to "coax" EMF to generate (nicer, if you wish) class names, so you won't be forced to use the schema's type names if you don't want to. :-)

2. I want more Eclipse IDE integration!

For example, when I edit the attribute interface, I don't want to type the Java interface name in a text box. I want something similar to those nice JDT dialogs where I can search and select for the Java interface:


In the next posts, we'll see how this can be done.

3. I want it to make me coffee & toast!

Okay, EMF is cool.. but not that cool :-)

Stay tuned!!!

Monday, January 7, 2008

Read...+ Write?

In a previous post I mentioned the possibilities opened up by having access to a C/C++ project's DOM AST within Eclipse. Now there's a new bugzilla in CDT to work on making this AST writable. Aside from the obvious benefit (aka "refactoring"), I can imagine a whole new bunch of neat features that can be made possible by this work: more intelligent C/C++ code generation, quick fix, among others.

Eclipse CDT is becoming more and more like the excellent JDT in terms of features and API, and this is great news for us C/C++ developers and Eclipse plug-in developers alike.