Piping to/from Ada program to a C++ program

2019-05-24 14:07发布

问题:

I have used pipes in C/C++ before but I'm working on setting up a pipe in some legacy Ada code...however I am still in the "learning" phase with Ada and there's a lot I still don't yet know.

That being said, I've been trying to figure out how pipes in Ada are setup & how to go about using them. I've only found these articles thus far:

  1. A Thick Ada 95 Binding for Unix Child Processes and Pipes
  2. Package: Util.Pipes
  3. Pipes - ada-util.

Don't get me wrong they have a lot of good knowledge in them, but 1 is geared towards Ada95 (I have the ability to compile up to Ada05), 2 just lists the functions, & 3 offers little in the way of explanation.

Does anyone know of a tutorial for Ada pipes? Or better yet, could someone give a quick example of how to implement a simple pipe in Ada?

I realize that this is not the most ideal question to ask, but I'm running out of "Google Combinations"...

回答1:

You might be more interested in Streams -- http://en.wikibooks.org/wiki/Ada_Programming/Input_Output/Stream_Tutorial

Especially since, if you make a package that binds a stream to a pipe you get free access with Type_Name'Read( stream, object ) & Type_Name'Write( stream, object ).



回答2:

Code

Compiled on Windows 10 with GNAT GPL 2015

with Ada.Text_IO;
with System;
with Interfaces.C;

procedure Main is

   package Pipes is
      type Pipe is private;
      type Get_Result is private;
      function Open_Read (Command : String) return Pipe;
      procedure Close (Stream : Pipe);
      function Get (Stream : Pipe) return Get_Result;
      function End_Of_File (Item : Get_Result) return Boolean;
      function To_Ada (Item : Get_Result) return Character;
   private
      use System;
      use Interfaces.C;
      type Pipe is new Address;
      type Get_Result is new int;
   end;

   package body Pipes is
      function popen (command : char_array; mode : char_array) return Address with Import, Convention => C, External_Name => "popen";
      function pclose (stream : Address) return int with Import, Convention => C, External_Name => "pclose";
      function fgetc (stream : Address) return int with Import, Convention => C, External_Name => "fgetc";
      function Open_Read (Command : String) return Pipe is
         Mode : constant char_array := "r" & nul;
         Result : Address;
      begin
         Result := popen (To_C (Command), Mode);
         if Result = Null_Address then
            raise Program_Error with "popen error";
         end if;
         return Pipe (Result);
      end;
      procedure Close (Stream : Pipe) is
         Result : int;
      begin
         Result := pclose (Address (Stream));
         if Result = -1 then
            raise Program_Error with "pclose error";
         end if;
      end;
      function Get (Stream : Pipe) return Get_Result is
      begin
         return Get_Result (fgetc (Address (Stream)));
      end;
      function End_Of_File (Item : Get_Result) return Boolean is (Item = -1);
      function To_Ada (Item : Get_Result) return Character is (Character'Val (Get_Result'Pos (Item)));
   end;

   procedure Test is
      use Ada.Text_IO;
      use Pipes;
      P : Pipe;
      C : Get_Result;
   begin
      P := Open_Read ("netstat");
      loop
         C := Get (P);
         exit when End_Of_File (C);
         Put (To_Ada (C));
      end loop;
      Close (P);
   end;

begin
   Test;
end;

Output

The output will differ from user to user .

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    192.168.1.140:49698    stackoverflow:https    ESTABLISHED
  TCP    192.168.1.140:49874    stackoverflow:https    ESTABLISHED
  TCP    192.168.1.140:49915    stackoverflow:https    TIME_WAIT
  TCP    192.168.1.140:49916    stackoverflow:https    TIME_WAIT


回答3:

Ada the language has nothing to say on the subject of pipes; they don't form part of the standard library. I suspect the same is true of C++ and the Boost library (not that I'm a user); pipes are an operating system facility.

Your article 1 contains source which compiles and works with Ada 2005 and Ada 2012 as well as (I expect) Ada 95 - at any rate on Unix systems. Won't that do?

Your article 2 - rather, the Util package found by poking around a bit - says it works on Windows and Unix.

The software available at your article 3 has the great advantage of being maintained!

As for a tutorial - since pipes aren't in the standard you have to use what the people who wrote the particular library you choose have provided. Articles 1 and 3 both contain demonstration programs (I haven't checked article 2). I suspect that's it!



回答4:

This may be overengineering a little, but there is gnat.sockets if you are allowed to use gnat libraries.

After all a pipe is a simpler version of a socket (or a socket being an expanded version of a pipe), both allow you to transfer data between tasks/processes.



回答5:

If you want to use Unix pipes in an Ada application, you should consider the POSIX Ada API, as it is a formal standard. One implementation of this is the "FLORIST" library.

The Crimeville language server is an example of how you can use pipes to handle communication between an Ada application and a legacy application with a pipe-friendly interface.



标签: c++ pipe ada