Reading a pipe or ouput of a C program into Matlab

조회 수: 36 (최근 30일)
Sampriti Bhattacharyya
Sampriti Bhattacharyya 2012년 11월 29일
답변: Sven Nießner 2020년 10월 13일
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!

답변 (4개)

Sven Nießner
Sven Nießner 2020년 10월 13일
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

Tobias Schmocker
Tobias Schmocker 2018년 4월 18일

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


Walter Roberson
Walter Roberson 2012년 11월 29일
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
Walter Roberson
Walter Roberson 2012년 12월 4일
memmapfile() cannot be used to access pipes.
Walter Roberson
Walter Roberson 2018년 4월 23일

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.

댓글을 달려면 로그인하십시오.


Sampriti Bhattacharyya
Sampriti Bhattacharyya 2012년 12월 5일
편집: Walter Roberson 2012년 12월 5일
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!

카테고리

Help CenterFile Exchange에서 Java Package Integration에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by