РЕДАКТИРОВАТЬ: я упростил свои коды, чтобы лучше показать ситуацию.
ЗАДАЧА: У меня есть работающая программа сокет-сервер/клиент, написанная на C. Я хочу улучшить ее, используя интерфейс Ada-C.
Функция C, которая получает пользовательский ввод, когда пользователь вводит математическую операцию как 2 + 5, 5 * 9, 10/2 или 10-9.
int read_message(void *buffer, int size, int timeout)
{
//Recevie
int n = recv(newfd, buffer, size, 0);
if(n == -1)
{
perror("Can not read message");
return -1;
}
return 1;
}
Клиент отправляет структуру на сервер, как указано ниже:
typedef struct
{
int number1;
int number2;
char operator;
}Operation;
Основная процедура Ады:
with Ada.Text_IO, communication_pkg, Ada.Exceptions, Interfaces.C;
use Ada.Text_IO, communication_pkg;
procedure Main is
package C_pkg renames communication_pkg;
begin
Put_Line(Integer'Image(C_pkg.open_communication));
Put_Line("Server is Open");
C_pkg.read_message;
exception
when Event: Open_Error =>
Put_Line("Can not open connection");
New_Line;
Put_Line(Ada.Exceptions.Exception_Name(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Message(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Information(Event));
when Event: Close_Error =>
Put_Line("Can not close connection");
New_Line;
Put_Line(Ada.Exceptions.Exception_Name(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Message(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Information(Event));
when Event: Can_not_read_error =>
Put_Line("Can not read");
New_Line;
Put_Line(Ada.Exceptions.Exception_Name(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Message(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Information(Event));
when Event: Read_timeout_error =>
Put_Line("Read timeout");
New_Line;
Put_Line(Ada.Exceptions.Exception_Name(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Message(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Information(Event));
when Event: others =>
Put_Line("Something else went wrong");
New_Line;
Put_Line(Ada.Exceptions.Exception_Name(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Message(Event));
New_Line;
Put_Line(Ada.Exceptions.Exception_Information(Event));
end Main;
Пакет под названием «связь_pkg», в котором есть функции и процедуры, открывающие, закрывающие и считывающие клиентское сообщение:
with Interfaces.C, Ada.Unchecked_COnversion, Ada.Text_IO;
use Interfaces.C, Ada.Text_IO;
with System;
package body Communication_pkg is
package C renames Interfaces.C;
function open return Integer;
pragma Interface(C, open);
pragma Interface_Name(open, "open");
function close return Integer;
pragma Interface(C, close);
pragma Interface_Name(close, "close_connection");
function read(buffer: in System.Address; size : in Integer; timeout: in Integer) return Integer;
pragma Interface(C,read);
pragma Interface_Name(read, "read_message");
function open_communication return Integer is
connection_status : Integer;
begin
connection_status := open;
if (connection_status = -1) then
raise Open_Error;
end if;
return connection_status;
end open_communication;
function close_communication return Integer is
connection_status : Integer;
begin
connection_status := close;
if(connection_status = -1) then
raise Close_Error;
end if;
return connection_status;
end close_communication;
procedure read_message is
size : Integer:=9;
timeout : Integer:=1;
read_message_status : Integer;
type byte is range 0..255;
type byte_array is array (Integer range 0..15) of byte;
--buffer : System.Address
buffer : byte_array;
begin
Put_Line("read message in");
read_message_status:=read(buffer'Address, size, timeout);
Put_Line(Integer'Image(read_message_status));
if(read_message_status = -1) then
raise Can_not_read_error;
elsif(read_message_status = -2) then
raise Read_timeout_error;
end if;
Put_Line("read message out");
for i in 0..15 loop
Put_Line(byte'Image(buffer(i)));
end loop;
end;
end Communication_pkg;
Основная процедура сначала открывает соединение и ожидает получения сообщения от клиента. Когда клиент отправляет структуру типа Operation, то, что я получаю в буфере, когда клиент вводит 2+5, выглядит примерно так, как указано ниже:
2 0 5 0 12331 11444 32688 0 2848 2737 32688 0 8864 64399 32767 0
Первый байт и третий байт в буфере (типа byte_array) всегда показывают первое и второе целое число, введенное клиентом. Однако в буфере нет оператора (типа char).
Как я могу полностью получить структуру оператора?
Unchecked_Conversion
отSystem.Address
доByte_Array
почти наверняка не то, что вам нужно. Это берет адрес (который в этой системе равен 4 или 8 байтам) и переинтерпретирует биты адреса какByte_Array
, что составляет 256 байтов. (2) Мы не знаем, что такоеOperation
. (3)for i in 0..8
выполняет цикл девять раз.i
будет принимать каждое значение 0, 1, ..., 7, 8. Это то, что вы хотите? (4) Возможно, нам потребуется посмотреть, как программа на языке Ada вызывает функцию C, включая любыеImport
/Export
аспекты/прагмы, которые вы используете. - person ajb   schedule 31.10.2013communication_pkg
на простоCommunications
. Мы все видим, что это пакет! - person Simon Wright   schedule 02.11.2013