2010-07-01 39 views
3

我相当新的德尔福&必须编写一个SOAP客户端。导入WSDL生成的代码(我明明是我显然必须符合服务器端无法更改)德尔福7:访问冲突 - TByteDynArray问题

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


[编辑]的要求,这里是我的代码,但 - 免责声明 - 我不得不破解它讲了很多(酌减)发布之前,所以它可能不会编译。双方PARMS到的sendMessage()非空

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); 
+3

这只是一个接口。你在做什么导致访问违规? – 2010-07-01 12:37:40

+0

+1是一个很好的问题。有两种方法可以解决这个问题 - 向我展示我的代码和数字为什么不起作用,或者有人发布了一些可以工作的代码,我可以将它与我自己的代码进行比较。好的,我会发布我的代码,但重要的是(我认为)这两个参数在调用时都是非空的 – Mawg 2010-07-01 13:17:02

+0

你真的从抢夺胜利的口袋中抢走了胜利,因为你使用了TByteDynArray而不是TBytes(这真的是只是一个字符串)。 – 2010-07-01 13:36:20

回答

3

新理念:你有范围在本单位检查?添加{$ R +}

如果要使用动态数组类型,则必须在访问构造函数时明确指定其长度,并在复制/分配时,必须非常小心。

不仅必须访问它的元素之前调用SetLength每个TByteDynArray:

SetLength(Fdata, MyDesiredLengthWhichIsGreaterThanZero): 

你也必须小心这里,我想这可能给你带来麻烦:

property data: TByteDynArray read Fdata write Fdata; 

你的汽车-generator为你编写代码,如果你真的知道你想要一个动态数组,你显然可以发布它。 (更新:最初我错了)。

正如Rob指出的那样,TRemotable不适用于索引属性,但对“字节数组”(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; 
+0

谢谢,沃伦(+1)。我刚刚发布了我的代码(删除了很​​多不相关的东西)。是的,我设定了长度。我可以编写Get/Set(),但不能直接通过访问属性来完成它? (告诉你我是德尔福的新手) – Mawg 2010-07-01 13:38:03

+0

你没有设置fdata的长度。你以为SetLength(SomethingElse,10),然后分配fdata = somthininse会起作用,而不会。 – 2010-07-01 13:38:39

+0

你需要阅读delphi语言指南,并理解何时使用动态数组,以及何时不使用,在这种情况下根本不使用动态数组类型。 – 2010-07-01 13:39:08