1

I have an executable (fossil scm) that is being invoked by my program externally through ::CreateProcess windows call. The stdout and stderr are then captured. Since the source code for fossil is available, I would prefer to create a static library out of it and issue calls directly. Currently, communication to fossil is done through the command line parameters, and the communication back is through the process return code, stdout and stderr. Fossil writes to stdout/err through printf and fprintf calls.

What is the best way to solve this with minimum alteration of fossil source? Is there a reliable and cross-platform way to intercept stdout/err and send it into a memory buffer?

ihamer
  • 101
  • 3

3 Answers3

3

You say that you want to

intercept stdout/err and send it into a memory buffer

This would indicate that you don't want to introduce an API for the SCM program and instead wish to carry on parsing the textual output without changing your existing code. If that is so then I see no point in changing from your current approach. What exactly is to be gained by using a memory buffer and static linking over the current approach?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    I like not having to deal with installing another executable. Still evaluating options including creating an API, and avoiding the stdout issues. – ihamer Jan 03 '11 at 15:26
3

You can do it in steps like these:

  • Rename the fossil's main function to something else so that you can call it
  • Before calling fossil's main, redirect stdout/stderr to the file of your choice with:

freopen("filename.out", "w", stdout);

  • Form an argument array, call fossil_main, read the output from the files.
  • You'll need to restore stdout stream state; there is no cross-platform mechanism for that, but you can use some pseudo-handles (i.e. CONOUT$ on Windows).

However, please note that this is fragile:

  • There may be global variables that are supposed to be zero-initialized at the beginning of main(), which will not be true for the second call to main()
  • fossil may change some process/thread state (locale, current directory, etc.), you won't be able to reliably restore it. An especially bad case of this is calling exit(n).
  • There will be no usual cleanup on process termination - expect file handles that are left open (so that you would not be able to open them again, if they're opened without sharing), memory leaks, etc.
  • Obviously, now crashes/hangs in fossil will be harder to handle (you can sometimes work around that)

Generally, you can do this, but don't unless you have a good reason to (i.e. performance) and you're ready to face the consequences and fix bugs yourself.

zeuxcg
  • 9,216
  • 1
  • 26
  • 33
0

Turn fossil into a shared library, and then use that from your custom program.

user502515
  • 4,346
  • 24
  • 20