Загрузить строку из потока Delphi в Oxygene

Я новичок в Oxygene и хочу читать строки из потока, сгенерированного Delphi. Я получаю этот поток через TCP. Вот как я сохраняю строки в поток на стороне клиента:

procedure SaveStringToStream(AStream: TStream; AString: String);
var
  StringSize: Integer;
  StringToSave: AnsiString;
begin
  StringToSave := Utf8Encode(AString);
  StringSize := Length(StringToSave);
  AStream.WriteBuffer(StringSize, SizeOf(StringSize));
  AStream.WriteBuffer(Pointer(StringToSave)^, StringSize);
end;

Как видите, я сначала добавляю размер строки в поток, а затем содержимое. Мой существующий метод загрузки строк из потока на стороне сервера (Oxygene) выглядит следующим образом:

function LoadStringFromStream(const aStream: NSInputStream): String;
begin
  var buf: array[1024] of uint8_t;
  var len: Integer:= 0;   
  len := aStream.&read(buf) maxLength(1024);
  if len > 0 then
  begin    
    nslog(len.stringValue);
    var data: NSMutableData := NSMutableData.alloc().initWithLength(0);
    data.appendBytes(@buf) length(buf[0]); 

    exit NSString.alloc().initWithData(data) encoding(NSStringEncoding.NSASCIIStringEncoding);             
  end;    
end;

Но это возвращает содержимое дыры, а не текущую часть.

РЕДАКТИРОВАТЬ: О, у меня была ошибка в серверном приложении... Теперь я могу читать строки, но не читать целочисленные значения (только до 256 бит). Для Objective-C я нашел этот код

- (int32_t)readInt32
{
    int32_t value = 0;

    if ([self read:(uint8_t *)&value maxLength:4] != 4)
    {
        NSlog(@"***** Couldn't read int32");
    }
    return value;
}

Вот код Oxygene:

function readInt32(const aStream: NSInputStream): Integer;
begin
  var value: int32_t := 0;
  var tmp:= uint8_t(@value);
  if aStream.&read(@tmp) maxLength(4) <> 4 then
    NSLog('***** Couldn''t read int32');  
  exit value;
end;

Но что-то идет не так, я ничего не понимаю. Ребята, вы знаете, что я должен делать?

2 ответа

Решение

Я думаю, что вы преобразовали код Objective-C (немного, но значительно) неправильно:

function readInt32(const aStream: NSInputStream): Integer;
begin
  var value: int32_t := 0;
  var tmp:= uint8_t(@value);
  if aStream.&read(@tmp) maxLength(4) <> 4 then
    NSLog('***** Couldn''t read int32');  
  exit value;
end;

В приведенном выше коде tmp объявляется как один байт и инициализируется с использованием приведения типа адреса переменной значения.

Таким образом, если переменная значения хранится по адресу $ 12345678 (глупый пример для краткости хранится в 32-битном формате), то tmp будет инициализирован значением $ 78. Затем вы передаете адрес переменной tmp в aStream.read(), которая пытается прочитать 4 байта в местоположение переменной tmp. Но tmp - только 1-байтовое значение!

Я думаю, что вам нужно изменить объявление tmp, чтобы сделать его указателем на unit8_t, а затем передать это непосредственно aStream.read():

  var value: int32_t := 0;
  var tmp:= ^uint8_t(@value);
  if aStream.&read(tmp) maxLength(4) <> 4 then
    NSLog('***** Couldn''t read int32'); 

Или исключите переменную tmp и передайте адрес значения напрямую с соответствующим приведением:

  var value: int32_t := 0;
  if aStream.&read(^uint8_t(@value)) maxLength(4) <> 4 then
    NSLog('***** Couldn''t read int32'); 

Этот последний подход более сравним с оригиналом Objective-C.

Сначала необходимо прочитать длину, а затем байты в кодировке UTF-8. Я вообще не знаю Oxygene, но код может быть таким:

var len: Integer:= 0;   
aStream.&read(len) maxLength(sizeof(Integer));
var buf := new uint8_t[len];
aStream.&read(buf) maxLength(len);

Я полностью ожидаю, что у меня неправильный синтаксис, но это общая идея!

Другие вопросы по тегам