Reading a pipe or ouput of a C program into Matlab

35 views (last 30 days)
Sampriti Bhattacharyya
Sampriti Bhattacharyya on 29 Nov 2012
Answered: Sven Nießner on 13 Oct 2020
I want to read out a pipe into matlab, but this isn't working. I have a windows computer
>>NET.addAssembly('System');
>> pipeStream = System.IO.Pipes.NamedPipeServerStream('testpipe', System.IO.Pipes.PipeDirection.Out)
Undefined variable "System" or function "System.IO.Pipes.PipeDirection.Out".
Then I tried popen
popen('C:\Documents\ServerPipe\ServerPipe.exe')
Undefined function 'popen' for input arguments of type 'char'.
>> popen(C:\Documents\ServerPipe\ServerPipe.exe)
|
Error: Unexpected MATLAB operator.
Infact poen doesnt exist in windows i think.
And yet, dateObj = System.DateTime.Now works fine! Help please! I need to get it working!

Answers (4)

Tobias Schmocker
Tobias Schmocker on 18 Apr 2018

Hi, it's an old topic, but i'm currently working on bidirectional inter process comunication between matlab and c# using a named pipe from .NET.

My Matlab code locks like this:

NET.addAssembly('System.Core');
pipeClient  = System.IO.Pipes.NamedPipeClientStream(".",'testpipe',...
    System.IO.Pipes.PipeDirection.InOut,...
    System.IO.Pipes.PipeOptions.Asynchronous);
if pipeClient.IsConnected ~= true
    pipeClient.Connect(2000);
end
sr = System.IO.StreamReader(pipeClient);
sw = System.IO.StreamWriter(pipeClient);
sw.WriteLine("Test Message");
sw.Flush();

in c# my code look's like this:

using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 4))
{
    StreamReader sr = new StreamReader(pipeServer);
    StreamWriter sw = new StreamWriter(pipeServer);
    Console.WriteLine("NamedPipeServerStream object created.");
      // Wait for a client to connect
      Console.Write("Waiting for client connection...");
      pipeServer.WaitForConnection();
      Console.WriteLine("Client connected.");
      do
      {
          try
          {
              string test;
              // receive message
              pipeServer.WaitForPipeDrain();
              test = sr.ReadLine();
              Console.WriteLine(test);
              //sw.WriteLine("Waiting");
              //sw.Flush();
          }
          catch (Exception ex) { throw ex; }
          finally
          {
              pipeServer.WaitForPipeDrain();
              if (pipeServer.IsConnected) { pipeServer.Disconnect(); }
          }
     } while (true);
}

Unfortunately, the pipe get's closed after each flush. Anyway, I hope this helps someone


Sven Nießner
Sven Nießner on 13 Oct 2020
Seems that I actualy made it. StreamWriter class is not nacessary.
You only need: ("this" because I created a class object)
% PipeName and Server defination
this.pipeName = "pipe_xxxx";
this.serverName = "localhost"; %for connection on the same local machine
% Add .Net
NET.addAssembly('System.Core');
% client pipeStream object is opened in InOut mode
this.pipeStream = System.IO.Pipes.NamedPipeClientStream(this.serverName,...
this.pipeName,...
System.IO.Pipes.PipeDirection.InOut);
% create Text encoder object
this.Encoder = System.Text.Encoding.Unicode;
You can connect to the server with
this.pipeStream.Connect(100);
The send function is the confusing part:
function this = Send(this,dataToStream)
if ~this.IsConnected
debugPrint(this,'Pipe isnt connecetd...');
return;
end
NET_Byte = this.Encoder.GetBytes(dataToStream);
bytes = NET_Byte.Length+2;
Out = NET.createArray('System.Byte', bytes);
debugPrint(this,char("begin send..." + string(bytes) + "bytes")); %DEBUG Print
debugPrint(this,char("Out Char: " + dataToStream)); %DEBUG Print
debugPrint(this,'bytes to send:'); %DEBUG Print
OutN = string(zeros(1,bytes));
for i = 1:1:bytes
if i <= NET_Byte.Length
Out(i) = NET_Byte(i);
end
OutN(i) = num2str(Out(i));
end
debugPrint(this, char(join(OutN))); %DEBUG Print
this.pipeStream.Write(Out,int32(0),bytes);
debugPrint(this,'finished send.'); %DEBUG Print
end
.Net uses Unicode UTF16 (in little-endian byte order) for the value returned from Encoding.Unicode.GetBytes() type, and UTF16 uses 2 bytes for each regular character. (UTF16 is also used for the string type.) PC-Beamage SW requires also a null character at the end of your unicode character.
Solution = UTF8 --> UTF16 Little Endian --> byte [] --> add a null character at the end of the byte array --> write byte array into the stream.
14:53:45 DEBUG: pipeBeamage_byte: Out Char: *CTLSTART
14:53:45 DEBUG: pipeBeamage_byte: bytes to send:
14:53:45 DEBUG: pipeBeamage_byte: 42 0 67 0 84 0 76 0 83 0 84 0 65 0 82 0 84 0 0 0
Same counts for receiving:
function received_data = Receive(this)
% receive data via pipe (decodes serialized byte stream and
% reconstitutes to originally sent format)
if ~this.IsConnected
debugPrint(this,'Pipe isnt connecetd...');
return;
end
read_buffer = NET.createArray('System.Byte',this.readBufferSize);
debugPrint(this,['receiving data...' num2str(this.readBufferSize) 'bytes buffer']);
ANS = this.pipeStream.Read(read_buffer, int32(0),int32(this.readBufferSize));
debugPrint(this,'receiving finished...');
BCHAR = uint8(zeros(1,ANS));
InN = string(uint8(zeros(1,ANS)));
for i = 1:1:ANS
BCHAR(i) = read_buffer(i);
InN(i) = num2str(BCHAR(i));
end
TCHAR = flip(native2unicode(flip(BCHAR),'unicode'));
debugPrint(this,[num2str(ANS) 'bytes received']);
debugPrint(this,['Bytes In: ' char(join(InN))]);
debugPrint(this,['Read Char: ' TCHAR]);
received_data = TCHAR(1:end-1);
end

Walter Roberson
Walter Roberson on 29 Nov 2012
The popen() system call does exist on MS Windows XP SP2 and later, but MATLAB does not offer an interface to that system call.
Unless you can find a way to use ActiveX, you would need to mex up a pipe interface.
Please note that MATLAB's built-in fwrite() and other I/O functions do not flush buffers, and that it is not certain that MATLAB's fseek() flushes buffers and there is no flush call in MATLAB. (These problems might possibly have changed in R2012b: work was done to allow diary() to flush more quickly, and that work might possibly imply something about flushing in general.)
  5 Comments
Walter Roberson
Walter Roberson on 23 Apr 2018

https://www.mathworks.com/matlabcentral/fileexchange/13851-popen-read-and-write is a File Exchange submission that can read or write pipes. Unfortunately it does not work bidirectionally.

Sign in to comment.


Sampriti Bhattacharyya
Sampriti Bhattacharyya on 5 Dec 2012
Edited: Walter Roberson on 5 Dec 2012
Walter, you are right. Could not figure out to use mex in this case, so tried out memmapfile. memmapfile can be used to access the output of a C code. I am reading output in real time, so I have a C program that reads it from the serial port and matlab which at the same time access the data which the C program is storing in a file. This might be useful for anyone, so here's the command
>>objname = memmapfile('Filename with filepath', ...
'Format', { 'uint64' [1] 'time'; 'double' [3] 'acc'; 'double' [3] 'ang'})
>>objname.Writable=true;
Thanks again!

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!