Pedro Alves
Pedro Alves

Reputation: 1728

How to call a CUDA C app in Java through ProcessBuilder?

I have a very complex application that uses CUDA and was write in C. This application is command-line only and now I want to build a GUI using Java Swing.

I don't want to rewrite C code, so I'm calling the command-line version using a ProcessBuilder object. This way I can read messages from it and show on a console inside the GUI.

This is the code I'm using:

String command = "myApp";
pb = new ProcessBuilder("bash", "-c",command);
pb.redirectErrorStream(true);
Process shell;
try {
        shell = pb.start();
        InputStream shellIn = shell.getInputStream();
        Drawer.writeToLog(convertStreamToStr(shellIn));
        shellIn.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

public String convertStreamToStr(InputStream is) throws IOException{
    if(is != null){
        Writer writer = new StringWriter();

        char[] buffer = new char[1024];
        Reader reader = new BufferedReader(new InputStreamReader(is,"UTF-8"));
        int n;
        while((n = reader.read(buffer)) != -1){
            writer.write(buffer,0,n);
        }
        is.close();
        return writer.toString();
    }else{
        return "";
    }
}

If I try something like "ls" command it works fine. However, for my app I get this error:

./myApp: error while loading shared libraries: libcudart.so.5.0: cannot open shared object file: No such file or directory

CUDA is installed and properly configured in my machine, I can execute this app correctly from Terminal. I imagine that the error is from Java Virtual Machine.

How can I fix it?

Upvotes: 0

Views: 218

Answers (1)

Eugene
Eugene

Reputation: 9474

This code works for me, I just tested it:

System.out.printf("[Starter#main] !\n");
final ProcessBuilder builder = new ProcessBuilder("absolute/path_to/your/executable");
builder.redirectErrorStream(true);
builder.environment().put("LD_LIBRARY_PATH",
    "/usr/local/cuda/lib64:/usr/local/cuda/lib");
final Process start = builder.start();
final InputStream outputStream = start.getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(outputStream));
String s;
while ((s = reader.readLine()) != null) {
    System.out.printf("[Starter#main] %s\n", s);
}

Gotchas:

  1. Make sure your application bitness matches your toolkit.
  2. Mac OS X variable is called "DYLD_LIBRARY_PATH"

Also note:

  1. Spawned process will inherit environment from your Java process, that is it should work fine if you run Java application with PATH and LD_LIBRARY_PATH configured as advised by CUDA toolkit installer.
  2. You may externalize variables setting and launching your app in a shell script - then all you have to do is just running shell with a given script.

Upvotes: 1

Related Questions