Fail to redirect native library's output from console

Discussion in 'Java' started by Jamaica R., May 5, 2007.

  1. Jamaica R.

    Jamaica R. Guest

    The DLL is c++ wrapping a Fortran subroutine, and called via JNI in
    the Java Application. I need to read the standard output from Fortran
    code, and display it to a dialog in Java Dialog. But using I/O
    redirection :
    System.setOut(new PrintStream(nativeDLL.getOutputStream()) ) can only
    read Java's standout output, -- it doesn't work on my DLL's output...
    Could you pls help me? Thanks in advance.

    We can't use Process.getInputStream() since this is a DLL rather an
    executable and the library is loaded without using Process, and a
    class LoopedStreams is used to implement input stream.


    public void run()
    {

    final LoopedStreams ls = new LoopedStreams();
    PrintStream ps = new PrintStream(ls.getOutputStream());
    System.setOut(ps);
    System.setErr(ps);
    try
    {
    LoadNativeDll.Init(m_command);
    new LoadNativeDll(m_workingDir+"\\").start();
    }
    catch (Exception ex)
    {//display ex
    return;
    }
    final BufferedReader br = new BufferedReader(new
    InputStreamReader(ls.getInputStream()));
    new Thread(new Runnable()
    {
    public void run()
    {
    try
    {
    String line;
    while ((line = br.readLine())!=null)
    {
    //feed the line to a dialog
    sleep(10);
    }
    fireStatusEvent(this,
    RegressionStatusEvent.REGRESSSION_STOP);
    }
    catch (Exception ex)
    {//display ex
    return;
    }

    }
    }).start();

    }

    // now the LoopedStreams wrapper
    public class LoopedStreams {
    private PipedOutputStream pipedOS =
    new PipedOutputStream();

    private boolean keepRunning = true;

    private ByteArrayOutputStream byteArrayOS =
    new ByteArrayOutputStream() {
    public void close()
    {
    keepRunning = false;
    try {
    super.close();
    pipedOS.close();
    }
    catch(IOException e) {
    // record error and deal with it
    // here simply stop it
    System.err.println("Fail to close
    ByteArrayOutputStream!");
    return;

    }
    }
    };


    private PipedInputStream pipedIS = new PipedInputStream() {
    public void close() {
    keepRunning = false;
    try {
    super.close();
    }
    catch(IOException e) { return; }
    }
    };


    public LoopedStreams() throws IOException {
    pipedOS.connect(pipedIS);
    startByteArrayReaderThread();
    } // LoopedStreams()


    public InputStream getInputStream() {
    return pipedIS;
    } // getInputStream()


    public OutputStream getOutputStream() {
    return byteArrayOS;
    } // getOutputStream()


    private void startByteArrayReaderThread() {
    new Thread(new Runnable() {
    public void run() {
    while(keepRunning) {
    // check the bytes size of the stream
    if(byteArrayOS.size() > 0) {
    byte[] buffer = null;
    synchronized(byteArrayOS) {
    buffer = byteArrayOS.toByteArray();
    byteArrayOS.reset(); // flush the buffer
    }
    try {
    // send data to PipedOutputStream
    pipedOS.write(buffer, 0, buffer.length);
    }
    catch(IOException e) {
    // record error and deal with it
    // here simply stop it
    System.err.println("Read thread
    error!");
    return;

    }
    }
    else // no data and turn the thread to sleep
    try {
    // check the ByteArrayOutputStream for new
    data every 1s
    Thread.sleep(1000);
    }
    catch(InterruptedException e) {}
    }
    }
    }).start();
    } // startByteArrayReaderThread()
    } // LoopedStreams
     
    Jamaica R., May 5, 2007
    #1
    1. Advertising

  2. On 4 May 2007 20:06:39 -0700, Jamaica R. wrote:
    > The DLL is c++ wrapping a Fortran subroutine, and called via JNI in
    > the Java Application. I need to read the standard output from
    > Fortran code, and display it to a dialog in Java Dialog. But using
    > I/O redirection :
    > System.setOut(new PrintStream(nativeDLL.getOutputStream()) ) can
    > only read Java's standout output, -- it doesn't work on my DLL's
    > output... Could you pls help me? Thanks in advance.
    >
    > We can't use Process.getInputStream() since this is a DLL rather an
    > executable and the library is loaded without using Process, and a
    > class LoopedStreams is used to implement input stream.


    If the native code prints to stdout, then the output goes to stdout
    regardless of what you do in Java. Note too that setOut() and similar
    methods do not actually change the stdout of the JVM process.

    You need to change the native code so that it returns its output or
    posts it directly to the dialog, instead of printing it. Or put it in
    a separate process so you can catch its output.

    /gordon

    --
     
    Gordon Beaton, May 5, 2007
    #2
    1. Advertising

  3. Jamaica R.

    Jamaica R. Guest

    Hi Gordon,

    Thanks for the reply.
    My native method is Fortran subroutine and wrapped into cpp library
    for Java to use. Fortran code does generate large data printed to
    stdout at random time.

    An executable by the fortran routine was successfully redirected by
    Process proc = (Runtime.getRuntime()).exec(m_commend);
    BufferedReader in = new BufferedReader(new
    InputStreamReader(proc.getInputStream()));
    which means Process's getInputStream() can obtain external routine's
    stdout and my dedicated dialog can display them.

    Now the same fortran subroutine is instead wrapped into cpp library
    for Java to load with JNI technique. With the code posted above,
    despite piped output/input and redirected system.out, fortran outputs
    are seen in the Eclipse (my development environment) Console panel,
    not my dedicated display dialog.

    So maybe it's not fault of my native code. The problem is how to get
    the DLL stdout, or how to use Process with a DLL...


    Best Rdgs,
    Jamaica


    On May 5, 2:58 pm, Gordon Beaton <> wrote:
    > On 4 May 2007 20:06:39 -0700, Jamaica R. wrote:
    >
    > > The DLL is c++ wrapping a Fortran subroutine, and called via JNI in
    > > the Java Application. I need to read the standard output from
    > > Fortran code, and display it to a dialog in Java Dialog. But using
    > > I/O redirection :
    > > System.setOut(new PrintStream(nativeDLL.getOutputStream()) ) can
    > > only read Java's standout output, -- it doesn't work on my DLL's
    > > output... Could you pls help me? Thanks in advance.

    >
    > > We can't use Process.getInputStream() since this is a DLL rather an
    > > executable and the library is loaded without using Process, and a
    > > class LoopedStreams is used to implement input stream.

    >
    > If the native code prints to stdout, then the output goes to stdout
    > regardless of what you do in Java. Note too that setOut() and similar
    > methods do not actually change the stdout of the JVM process.
    >
    > You need to change the native code so that it returns its output or
    > posts it directly to the dialog, instead of printing it. Or put it in
    > a separate process so you can catch its output.
    >
    > /gordon
    >
    > --
     
    Jamaica R., May 5, 2007
    #3
  4. Jamaica R.

    Chris Smith Guest

    Jamaica R. <> wrote:
    > An executable by the fortran routine was successfully redirected by
    > Process proc = (Runtime.getRuntime()).exec(m_commend);
    > BufferedReader in = new BufferedReader(new
    > InputStreamReader(proc.getInputStream()));
    > which means Process's getInputStream() can obtain external routine's
    > stdout and my dedicated dialog can display them.


    Right. When you execute a subprocess, Java automatically captures the
    standard input, output, and error streams of that other process and
    gives you access to them.

    That is fundamentally different from running native code in your own
    process. That native code uses your process's standard streams. So
    you've got two options:

    1. Run the Fortran code as a separate process.

    2. Change something so that the Fortran code isn't really printing to
    standard output. This may be as simple as calling freopen from the C++
    wrapper.

    --
    Chris Smith
     
    Chris Smith, May 5, 2007
    #4
  5. Jamaica R.

    Guest

    > So you've got two options:
    >
    > 1. Run the Fortran code as a separate process.
    >
    > 2. Change something so that the Fortran code isn't really printing to
    > standard output. This may be as simple as calling freopen from the C++
    > wrapper.
    >
    > --
    > Chris Smith


    Chris Smith,

    Thank you.

    I am currently trying to understand the difference between thread and
    process. Is it true that Process can only be invoked from an
    executable command but never from a dynamic library?

    By "1. Run the Fortran code as a separate process. ", do you mean I
    have to change the fortran code into an ".exe"?

    For "2. Change something so that the Fortran code isn't really
    printing to stdout", do you mean modify fortran code to write to a
    file, or return a string to C and then to Java?
    If so, I don't think it is applicable because the data to print might
    be thousands of lines spending tons of time, so share a string is not
    preferred. And I think that concurrent write and read access for a
    file is not permitted in Windows.

    Great appreciated if you could you please provide further
    instruction...

    Regards,
    Jamaica
     
    , May 6, 2007
    #5
  6. Jamaica R.

    Chris Smith Guest

    <> wrote:
    > I am currently trying to understand the difference between thread and
    > process. Is it true that Process can only be invoked from an
    > executable command but never from a dynamic library?


    In general, it's true that the process you invoke will get its code from
    an executable file -- possibly in conjunction with one or more dynamic
    libraries. You can't invoke a dynamic library as its own process. (I'm
    ignoring a certain complicated exception to this rule on the Windows
    operating system; you should, too.)

    If you really meant what you said -- invoked "from" -- then you're
    incorrect. It doesn't matter whether the code that actually invokes the
    process is in a library or not.

    > By "1. Run the Fortran code as a separate process. ", do you mean I
    > have to change the fortran code into an ".exe"?


    Either that or write another program to call it. That other program
    could even be written in Java; what matters is that it's a separate
    process, so you can get its standard output as a stream.

    > For "2. Change something so that the Fortran code isn't really
    > printing to stdout", do you mean modify fortran code to write to a
    > file, or return a string to C and then to Java?


    It's a general strategy. Use a file, or a string, or a named pipe, or
    whatever. The point is that you can't redirect your Fortran code's
    stdout from Java, so you'll have to do something in either the C++ or
    Fortran code.

    --
    Chris Smith
     
    Chris Smith, May 6, 2007
    #6
  7. Jamaica R.

    Jamaica R. Guest

    On May 7, 5:04 am, Chris Smith <> wrote:
    > <> wrote:
    > > I am currently trying to understand the difference between thread and
    > > process. Is it true that Process can only be invoked from an
    > > executable command but never from a dynamic library?

    >
    > In general, it's true that the process you invoke will get its code from
    > an executable file -- possibly in conjunction with one or more dynamic
    > libraries. You can't invoke a dynamic library as its own process. (I'm
    > ignoring a certain complicated exception to this rule on the Windows
    > operating system; you should, too.)
    >
    > If you really meant what you said -- invoked "from" -- then you're
    > incorrect. It doesn't matter whether the code that actually invokes the
    > process is in a library or not.
    >
    > > By "1. Run the Fortran code as a separate process. ", do you mean I
    > > have to change the fortran code into an ".exe"?

    >
    > Either that or write another program to call it. That other program
    > could even be written in Java; what matters is that it's a separate
    > process, so you can get its standard output as a stream.
    >
    > > For "2. Change something so that the Fortran code isn't really
    > > printing to stdout", do you mean modify fortran code to write to a
    > > file, or return a string to C and then to Java?

    >
    > It's a general strategy. Use a file, or a string, or a named pipe, or
    > whatever. The point is that you can't redirect your Fortran code's
    > stdout from Java, so you'll have to do something in either the C++ or
    > Fortran code.
    >
    > --
    > Chris Smith


    Thank you!
    I'll try on a seperate simple Java app first...

    Jamaica
     
    Jamaica R., May 6, 2007
    #7
  8. Jamaica R. wrote:
    > Hi Gordon,
    >
    > Thanks for the reply.
    > My native method is Fortran subroutine and wrapped into cpp library
    > for Java to use. Fortran code does generate large data printed to
    > stdout at random time.
    >
    > An executable by the fortran routine was successfully redirected by
    > Process proc = (Runtime.getRuntime()).exec(m_commend);
    > BufferedReader in = new BufferedReader(new
    > InputStreamReader(proc.getInputStream()));
    > which means Process's getInputStream() can obtain external routine's
    > stdout and my dedicated dialog can display them.


    That can be implemented using pipes, without any special interception.

    Telling a new job where to send its standard out is very different from
    trying to change the rules for part of a running process.

    > So maybe it's not fault of my native code. The problem is how to get
    > the DLL stdout, or how to use Process with a DLL...


    Just write a wrapper application, in any convenient language, that calls
    the dll. The application's command line parameters can be used to tell
    it initial parameters to pass to the dll. Your Java job can then use
    ProcessBuilder and Process to control and communicate with the wrapper,
    which in turn controls the dll.

    Patricia
     
    Patricia Shanahan, May 8, 2007
    #8
  9. Jamaica R.

    Jamaica R. Guest

    hi Patricia,

    Thank you very much!
    What you recommend is exactly what I finally managed to get through
    today ^_^
    The "wrapper" is written in an independent Java application. Then the
    Process stands to help me out.

    Jamaica

    On May 8, 11:05 pm, Patricia Shanahan <> wrote:
    >
    >
    > Just write a wrapper application, in any convenient language, that calls
    > the dll. The application's command line parameters can be used to tell
    > it initial parameters to pass to the dll. Your Java job can then use
    > ProcessBuilder and Process to control and communicate with the wrapper,
    > which in turn controls the dll.
    >
    > Patricia
     
    Jamaica R., May 8, 2007
    #9
  10. Jamaica R.

    Jamaica R. Guest

    hi Patricia,

    Thank you very much!
    What you recommend is exactly what I finally managed to get through
    today ^_^
    The "wrapper" is written in an independent Java application. Then the
    Process stands to help me out.

    Jamaica

    On May 8, 11:05 pm, Patricia Shanahan <> wrote:
    >
    >
    > Just write a wrapper application, in any convenient language, that calls
    > the dll. The application's command line parameters can be used to tell
    > it initial parameters to pass to the dll. Your Java job can then use
    > ProcessBuilder and Process to control and communicate with the wrapper,
    > which in turn controls the dll.
    >
    > Patricia
     
    Jamaica R., May 8, 2007
    #10
  11. Jamaica R.

    yosri Guest

    On 8 mai, 17:24, "Jamaica R." <> wrote:
    > hi Patricia,
    >
    > Thank you very much!
    > What you recommend is exactly what I finally managed to get through
    > today ^_^
    > The "wrapper" is written in an independent Java application. Then the
    > Process stands to help me out.
    >
    > Jamaica
    >
    > On May 8, 11:05 pm, Patricia Shanahan <> wrote:
    >
    >
    >
    > > Just write a wrapper application, in any convenient language, that calls
    > > the dll. The application's command line parameters can be used to tell
    > > it initial parameters to pass to the dll. Your Java job can then use
    > > ProcessBuilder and Process to control and communicate with the wrapper,
    > > which in turn controls the dll.

    >
    > > Patricia


    Hi Jamaica,

    I encoutered the same problem as described this thread , can you tell
    me more about the Wrapper that you used to solve the problem?

    Thank you in advance.
     
    yosri, Jun 1, 2007
    #11
  12. Jamaica R. wrote:
    > The DLL is c++ wrapping a Fortran subroutine, and called via JNI in
    > the Java Application. I need to read the standard output from Fortran
    > code, and display it to a dialog in Java Dialog. But using I/O
    > redirection :
    > System.setOut(new PrintStream(nativeDLL.getOutputStream()) ) can only
    > read Java's standout output, -- it doesn't work on my DLL's output...
    > Could you pls help me? Thanks in advance.


    I can understand that you have found alternative solutions, but
    if you want a solution for the original problem then see:
    http://www.vajhoej.dk/arne/eksperten/jniredirect/

    If the Fortran RTL are build on top of the C RTL, then
    it should work for a C++ wrapper around Fortran as well.

    Arne
     
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=, Jun 9, 2007
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nishi Bhonsle

    Redirect output from console to a file

    Nishi Bhonsle, Jan 15, 2004, in forum: Java
    Replies:
    6
    Views:
    29,635
    Tony Morris
    Jan 18, 2004
  2. Arcor

    Native Console Output

    Arcor, Sep 12, 2004, in forum: Java
    Replies:
    3
    Views:
    550
    Boudewijn Dijkstra
    Sep 13, 2004
  3. 28tommy
    Replies:
    2
    Views:
    11,277
    28tommy
    Dec 29, 2005
  4. Replies:
    5
    Views:
    3,435
    James Kanze
    Mar 4, 2008
  5. nickname
    Replies:
    7
    Views:
    1,075
    Nobody
    Aug 26, 2009
Loading...

Share This Page