Shell question

I need to interface to a command line program that typically inputs and outputs files… But using files written to disk would slow things way down…

This will need to work both on Mac and Windows…but I am pretty clueless about command line/shel stuff.

This from the command line help on a Mac:

[quote]obabel[-i] [-o] -O [Options]
The extension of a file decides the format, unless it is overridden
by -i or -o options, e.g. -icml, or -o smi
See below for available format-types, which are the same as the
file extensions and are case independent.
If no input or output file is given stdin or stdout are used instead.
[/quote]

From Xojo using teh steel class, how would I use stdin instead of an input file to send it the the input data and Stdout to get the output?
An example of that is not provided among teh Xojo shell example projects.

  • Thanks
    karen

First, How big are the files? I’d be worried about sending multiple megabyte data via the shell (I could be entirely wrong there).

In any case, you would use the shell in asynchronous or interactive mode. Call the program with the data on the same line:

myprogram.app -data(or whatever flag) yourvastamountofdatahere. . . .

Then, set up a timer to watch the dataAvailable event on the shell buffers and add their contents to your return data structure until the program terminates.

I use files to send & receive data to/from a python program and use an asynchronous shell because the program can run a half-hour or more on occasion but usually it’s a couple seconds. In this day and age of SSDs and fancy OS file-caching, using files can be surprisingly fast.

Dave

WINDOWS

when you use the shell it is best to use the full paths

for example (yes you need the quotes), i have padded it out so you can see what is needed

dim q as string =chr(34)
dim s, res as string
s=q
s=s+“C:\Users\stever\Desktop\some folder\obabel.exe” ’ this is the full path to your EXE
s=s+q

s=s+" " ’ just a space

s=s+q
s=s+“C:\Users\stever\Desktop\some folder\the in file.ext” ’ this is the full path to your in file
s=s+q

s=s+" " ’ just a space

s=s+" -O" ’
s=s+q
s=s+“C:\Users\stever\Desktop\some folder\the out file.ext” ’ this is the full path to your output file
s=s+q

dim sh as shell
sh.timeout = 30*1000 ’ 30 seconds - change this as required

res = sh.execute(s)

msgbox res

’ you can normally look at what is returned to see if it worked or not

pretty simple example but the options, in type and out type probably wont need quotes.

thanks
damon

David is right, we need to know something about the data you are looking to send. If it’s fairly short and not complicated (pure alphanumeric, for example), you should able to get away with something like this:

dim cmd as string = "/path/to/obabel <options>"
cmd = "echo '" + myData + "' | " + cmd

dim sh as new Shell
sh.Execute cmd
dim result as string = sh.Result

Thanks for the replies!

[quote=410899:@Kem Tekinay]David is right, we need to know something about the data you are looking to send. If it’s fairly short and not complicated (pure alphanumeric, for example), you should able to get away with something like this:
[/quote]

It is straight alphanumeric data that is supposed to be in the file… As for how long that depends on how I code it… The app is designed to handle files with thousands of entries, but I don’t think I will need more than 20-30 with probably < 300 characters per entry.

[code]
dim cmd as string = "/path/to/obabel "
cmd = “echo '” + myData + "’ | " + cmd

dim sh as new Shell
sh.Execute cmd
dim result as string = sh.Result
[/code][/quote]

I will play with that and see if I can get it to work…

BTW the app is open source called Open Babel and is meant to convert and search various representation of chemical structures for chemical informatics applications.

They have a lower level toolbox library written in C++ that is a more flexible that can be called from (besides C++) various languages using available bindings (Python, Ruby, Java, Perl, C#) but not Xojo- none of which I know.

I thought about looking into declaring into the lower level informatics toolbox library included in the package. It is composed of many C++ classes and small programs and plugins, but decided that was impractical for me. As I don’t known much about declares or C++ or writing plugins, I would have to figure out how to compile all of that from scratch and then have to learn all the classes… Way too much for me!

So I figured the shell approach is best for my available time and capabilities

Thanks,

  • Karen

I think that’s a fine idea, and has an additional benefit. You can put the Shell in Interactive mode (Mode = 1) and the results will come back in the DataAvailable event. The advantage is that you can have more than one running simultaneously and it will naturally take advantage of all processors/cores on the machine.

I got Kem’s code to work for a Mac, would the same code work in a Windows shell (I have not installed Open Babel on a Windows machine yet)?

As Windows is not unix based, I don’t know if the same shell code would work…

Thanks,

  • karen

One more shell question… I have not used them a lot…

Is it better to create a new shell object every time or keep one around and reuse it?

I have always just created a new one each time, but it was for occasional use… in this app it could potentially get called a lot!

What is the cost (if any) of keeping an instance around vs creating new one for each call to the command line app.

At times there could be hundreds of consecutive calls.

  • karen

You might have to modify the command the Windows side, but otherwise yes, it should be mostly the same thing. However, there is a Timeout property that comes into play on Windows. Either set it to some reasonable number to allow the job to finish or to -1 for no timeout.

If you are planning hundreds of consecutive calls, I’d leave one Shell connected and reuse it, but again, consider spreading that over many Shells to take advantage of multiple processors.