« Earlier2 items total Later »

IRB and issuing shell commands with pipes.

If you wish to issue pipe two commands together in bash then it is easy.

ls /bin | grep grep


generates

bzegrep
bzfgrep
bzgrep
egrep
fgrep
grep
zegrep
zfgrep
zgrep


but how to do this neatly in IRB

How about like


require './shell.rb'
Sh.ls("/bin").grep("grep")


using the library


module Sh
    class Command

        def initialize(cmd, *args)
            @cmd = cmd
            @args = args
            @io = nil
        end

        def inspect
            to_s
        end

        def to_str
            to_s
        end

        def to_s
            call
            str = @io.read
            @io.close
            str
        end

        def | other
            call
            other.call(@io)
        end

        def method_missing(name, *args)
            self | Command.new(name, *args)
        end

        def call (io=nil)

            # The @io object can only be assigned
            # once
            return self if @io

            command =  @cmd.to_s + " " + @args.join(" ")

            if io
                #  We need a new process
                #  and a pipe to connect the
                #  this command to the previous
                #  command in the chain.
                rd, wr = IO.pipe

                if fork
                    # Parent
                    wr.close
                else
                    # Child
                    rd.close
                    begin
                        # Reconnect the STDIN of the
                        # new process to the io parameter
                        $stdin.reopen(io)
                        IO.popen command do |f|
                            while txt = f.read(4096)
                                wr.write txt
                            end
                        end
                    rescue Errno::EPIPE
                        # Ignore the broken pipe
                        # cause the other process
                        # has thrown away the pipe
                        # earlier than we used outs
                    ensure
                        wr.close
                    end
                    exit
                end
                @io = rd
            else
                # This command is executed standalone.
                @io = IO.popen command
            end
            self
        end
    end

    def self.method_missing (name, *args)
        Command.new(name, *args)
    end
end

Serialization and deserialization of matlab data

To serialize any matlab data type create a file called mserialize.c and mdeserialize and fill it thus

#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
                 const mxArray *prhs[])
{
   plhs[0] = (mxArray *) mxSerialize(prhs[0]);
}


#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs,
                 const mxArray *prhs[])
{
   plhs[0] = ( mxArray * ) mxDeserialize(mxGetData(prhs[0]), mxGetNumberOfElements(prhs[0]));
}


Note the above code uses unsupported matlab API so don't bug Mathworks tech support if it doesn't work or your matlab session crashes or your computer explodes :)

You use the functions thus

foo.a = 10

data = mserialize(foo)

bar = mdeserialize(data)




##################

Following from a post from CSSM by Dr Tristram J. Scott is another technique. I quote the whole post here

Related to this, I think, is the (also undocumented) save stdio command:

>> save stdio x


This sends x to stdout with a bit of header information, in much the same
format as the save command might have done. There is a corresponding load
command.

This allows you to use MATLAB in a pipe in the way which is implemented for the MATLAB engine under UNIX.

If you start a MATLAB engine using a tee you can see a bit of what goes on

#define MYMATLAB "tee /tmp/f1 | matlab -nojvm | tee /tmp/f2 -"
   if (!(ep = engOpen(MYMATLAB))) {
      syslog(LOG_ERR, "Can't start MATLAB engine.");
      syslog(LOG_ERR, "Exiting.");
      exit(EXIT_FAILURE);
   }


Send it a command such as x = rand(3), then use engGetVariable(ep, "x") to get MATLAB to send the variable through the pipe up to your C code, ready for mxGetPr() or whatever to use it. Examine the /tmp/f1 and /tmp/f2 files
to see the wrapper which the engine puts around all of your engEvalString() calls.

« Earlier2 items total Later »




Sponsored by

Sole Central

Your one stop shop for Birkenstock and Crocs shoes and sandles.