1

私は 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;

ご覧のとおり、最初に文字列のサイズをストリームに追加し、次にコンテンツを追加します。サーバー側(Oxgene)のストリームから文字列をロードする既存の方法は次のようになります。

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;

しかし、何かがうまくいかず、値が得られません。私が何をしなければならないか知っていますか?

4

2 に答える 2

0

あなたは 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は 1 バイトとして宣言され、変数のアドレスの型キャストを使用して初期化されます。

したがって、value変数がメモリ アドレス$12345678に格納されている場合(簡潔にするために 32 ビットにしておくばかげた例)、tmpは値$78で初期化されます。次に、 tmp変数のアドレスをaStream.read()に渡します。これは、 tmp変数の場所に 4 バイトを読み取ろうとします。 しかし、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 のオリジナルに直接匹敵します。

于 2014-08-28T04:59:48.660 に答える