Showing posts with label IPC. Show all posts
Showing posts with label IPC. Show all posts

Tuesday, March 5, 2013

How Java and C or C++ can talk on Linux

Linux is all about interoperability. That is more of IPC stuff. Without any type safety we can open pipe and pass arbitrary chunk of data between native process and Java process. No need for JNI, let the data flow. Secret of our success is function popen(), for more info invoke man popen from terminal. All actions are initiated from native code, so here is declaratively C++ native code to start Java listener and send chunk of data to it:


Without that C++ include statement it would look like plain C. It will create process java SomeOtherClass and open pipe to it for writing. Naturally before we run native part of system we should compile Java code. Here is Java listener:

import java.io.BufferedInputStream;

class SomeOtherClass {
    public static void main(String args[]) throws Exception {
        BufferedInputStream bis = new BufferedInputStream(System.in, 132);
        StringBuffer sb = new StringBuffer();
        int i;
        while ((i = bis.read()) != -1) {
            sb.append((char) i);
        }
        System.out.println("SomeOtherClass got message : " + sb.toString());
    }
}


When we run native binary it will start Java class and send to it message. In its turn Java class will use BufferedInputStream to read standard input and turn stream of integers into String. If we want we can make C++ listening and Java talking. Here is the now really C++ code:


As last time Java code must be compiled prior to executing native one. Here is Java code:

public class SomeClass {
    public static void main(String[] args) {
        String msg = "Greetings from Java no: ";
        for (int i = 0; i < 10; i++) {
            System.out.println(msg + i);
        }
    }
}


We have less code but more output, obvious rise in productivity due to OO approach.
Not very useful, but things could be done this way.

Nostalgic moments

While trying to do:


I was greeted with error message:

invalid conversion from ‘int’ to ‘const char*’

C FILE* was expelled from ISO/ANSI C++ streams. Luckily there is workaround, one can subclass std::streambuf as described here. Sometimes one can find useful things on StackOverflow ;-)


Monday, March 4, 2013

Pipes and even more interesting Named Pipes

Pipes are very user friendly form of IPC on Linux. We are frequently using them in terminal, for example on Debian:

$ dpkg -l | grep gimp

We want to see only installed packages which are containing gimp in its name. Easy way to get pipe is to declare integer array and fork. Since child process gets all variables from parent it gets pipe as well.


Naturally such client server code is clumsy to write and creators of UNIX invented named pipes. Those are nothing but files and we can create them from terminal using mknod command and p switch, we want FIFO - first in first out storage:

$ mknod TESTFIFO p

Now if we do ls -l on our FIFO we will see that it got different color from other files and additional markings, letter p:

prw-r--r-- 1 borg borg 0 Mar  4 22:28 TESTFIFO

You do not have to be programmer to create FIFO. One can go even further and open two terminals, in the first execute cat > TESTFIFO and in the second one cat TESTFIFO, now everything what you write in the first one will appear in the second one, after you hit enter.
After all that fun we may go back to programming and create simple client and server which will use FIFO to talk. Client code:


Then server code:


Whoever starts first will be blocked until other side of pipe is open. When server exits, client exits as well. Very simple and user friendly.
Those examples are very much influenced by Linux Programmer's Guide by Scott Burkett and Beej's Guide to Unix IPC. The second one is quite entertaining and you can find it here with few other books and tutorials.
Next couple of posts will be about Java and pipes and Android and pipes and finally about NDK and pipes.