Delphi 7:访问冲突--TByteDynArray问题

时间:2010-07-01 12:28:18

标签: delphi

我对Delphi& amp;必须编写SOAP客户端代码。导入WSDL会生成此代码(我显然无法更改,因为我显然必须遵守服务器端)

  DataPart            = class;             
  Message             = class;             
  eMessage            = class;             

  eventType = ( send, delete, etc );

  DataPart = class(TRemotable)
  private
    FhasData: Boolean;
    Fdata: TByteDynArray;
  published
    property hasData: Boolean read FhasData write FhasData;
    property data: TByteDynArray read Fdata write Fdata;
  end;
  Message = class(TRemotable)
  private
    FMessageID: Int64;
    Ftimestamp: TXSDateTime;
    Fevent: eventType;
    FmagicNumber: WideString;
    FDataPart: DataPart;
  published
    property MessageID: Int64 read FMessageID write FMessageID;
    property timestamp: TXSDateTime read Ftimestamp write Ftimestamp;
    property event: eventType read Fevent write Fevent;
    property magicNumber: WideString read FmagicNumber write FmagicNumber;
    property DataPart: DataPart read FDataPart write FDataPart;
  end;

  eMessage = class(TRemotable)
  private
    FencryptedMessage: TByteDynArray;
    Fdata: DataPart;
  published
    property encryptedMessage: TByteDynArray read FencryptedMessage write FencryptedMessage;
    property data: DataPart read Fdata write Fdata;
  end;

  MyApplicationPortType = interface(IInvokable)
  ['{99767D33-6B4A-7547-4DAC-0608095CAC70}']

    function  sendMessage(const encryptedMessage: TByteDynArray; const data: DataPart): WideString; stdcall;
  end;

任何人都可以用虚拟值编写一个示例来调用sendMessage()而不会导致访问冲突吗?我真的不知道如何处理TByteDynArray


[编辑]按照要求,这是我的代码,但是 - 免责声明 - 在发布之前我不得不破解它(减少它),所以它可能无法编译。 sendMessage()的parms都是非null

  var theMessageArray: TByteDynArray;
      theResult : WideString;
      messageData : TByteDynArray;
      i : Integer;
begin
  theMessage.messageID := theMessage.messageID + 1;
  theMessage.timestamp := TXSDateTime.Create();
  theMessage.timestamp.AsDateTime := Now();
  theMessage.event := delete;
  theMessage.magicNumber  := 'magic # ' + IntToStr(theMessage.messageID);

  SetLength(messageData, 1);
  messageData[0] := 0;

  theMessage.dataPart.hasData := True;
  messageData := theMessage.dataPart.messageData;

  SetLength(messageData, $1000 * dataSize);

  for i := 0 to $1000 * dataSize - 1 do
        messageData[i] := i and $FF;

  theMessage.DataPart.messageData := messageData;

  theMessageArray := TByteDynArray(theMessage);
  theResult := (HTTPRIO1 as MyApplicationPortType).sendMessage(theMessageArray, theMessage.dataPart);

1 个答案:

答案 0 :(得分:3)

新想法:您是否在此单元中进行了范围检查?添加{$ R +}

如果要使用动态数组类型,则必须在访问它之前明确在构造函数中设置其长度,并且在复制/赋值时,您也必须非常小心。

在访问其元素之前,您不仅必须在每个TByteDynArray上调用SetLength:

SetLength(Fdata, MyDesiredLengthWhichIsGreaterThanZero):

你在这里也要小心,我想这可能会让你陷入困境:

  property data: TByteDynArray read Fdata write Fdata;

你的自动生成器为你制作了这个代码,如果你真的知道你想要一个动态数组,你显然可以让它发布。 (更新:我最初错了)。

正如Rob指出的那样,TRemotable不能与索引属性一起使用,但是对于“byte of byte”(TByteDynArray)属性可以正常工作,所以如果你做的一切都正常,你就不需要停止使用TByteDynArray了(我错了关于那个最初)。

如果是我从头开始写这个,我会使用“字符串”类型而不是TBytes。我想知道它为什么不使用TBytes,但我知道您正在使用一些自动生成的WSDL生成器代码实现SOAP客户端。因此,应该非常可能使您的代码不会崩溃。

see also this Related question

我不知道如何编写SOAP客户端,但看起来你的代码做了一些狡猾的事情。看起来你需要修复你的动态数组处理,包括“呃 - 哦,你为什么要在这里做一个演员”问题Rob向你指出。但是,看起来您也可以自由更改类型,因为看起来您必须使用TRemotable机制已知并处理的类型。

至于你的要求,这应该有效:

  procedure TestMe( whatever:TWhatever );
  var 
    FData:TByteDynArray;
  begin
     SetLength(FData,2); 
     FData[0] := 10; 
     FData[1] := 20;
     sendMessage(FData, whatever);
  end;