2015-02-11 73 views
-1

我不是一個Delphi程序員,我需要在程序中做一些更改並重新編譯。但是,問題是我無法重新編譯我已有的源代碼。我追溯了這個問題,這似乎是因爲Delphi XE7使用Indy 10而不是Indy 9.並且由於Indy 10中不存在TIdPeerThread,所以我得到錯誤。德爾福XE7,麻煩編譯,未聲明的標識符:'TIdPeerThread'

如果你能幫助我修改代碼,以便與Indy 10兼容,我可以在Delphi XE7中重新編譯它,我將非常感激。

library TCPServer; 

uses 
    SysUtils, 
    Classes, 
    Forms, 
    IdTCPServer, 
    IdTCPClient, 
    Dialogs; 

{$R *.res} 

const 
    nInputs = 60; 
    nOutputs = 60; 
type 
    ts = array[0..255] of char; 
    array_in = array[1..nInputs] of single; 
    array_out = array[1..nOutputs] of single; 
    Thelper = class 
    IdTCPServer: TIdTCPServer; 
    procedure IdTCPServer1Execute(AThread: TIdPeerThread); 
    procedure IdTCPServer1Connect(AThread: TIdPeerThread); 
    procedure IdTCPServer1DisConnect(AThread: TIdPeerThread); 
    end; 

var 
    helper: Thelper; 

    server_to_be_send: string = ''; 
    server_lastread: string = ''; 

    firsttimecall : boolean = true; 

    inputvector_delay : array_in; 
    outputvector_delay : array_out; 
    time_old : single = -1.0; 

procedure Thelper.IdTCPServer1Connect(AThread: TIdPeerThread); 
begin 
    try 
    Write('Connect from '+AThread.Connection.Socket.Binding.IP+':'+IntToStr(AThread.Connection.Socket.Binding.Port)); 
    WriteLn(' (peer '+AThread.Connection.Socket.Binding.PeerIP+':'+IntToStr(AThread.Connection.Socket.Binding.PeerPort)+')'); 
    except 
    end; 
end; 

procedure Thelper.IdTCPServer1DisConnect(AThread: TIdPeerThread); 
begin 
    try 
    Write('Disconnect to '+AThread.Connection.Socket.Binding.IP+':'+IntToStr(AThread.Connection.Socket.Binding.Port)); 
    WriteLn(' (peer '+AThread.Connection.Socket.Binding.PeerIP+':'+IntToStr(AThread.Connection.Socket.Binding.PeerPort)+')'); 
    except 
    end; 
end; 

procedure Thelper.IdTCPServer1Execute(AThread: TIdPeerThread); 
var 
    ii : Integer; 
begin 
    IdTCPServer.OnExecute := nil; 
    while true do 
    begin 
    Application.ProcessMessages(); 
    if (server_to_be_send<>'') then 
    begin 
     AThread.Connection.WriteLn(server_to_be_send); 
     server_to_be_send := ''; 
     server_lastread := AThread.Connection.ReadLn('*',5000); 
     if server_lastread='' then 
     for ii:=1 to nInputs do server_lastread := server_lastread + '0;'; 
    end; 
    end; 
end; 

Procedure tcplink(na:integer;var inputvector : array_in; 
        nb:integer;var outputvector: array_out);stdcall; 
var 
    i : Integer; 
    st : string; 
begin 

    // Ensure English locale decimal separator symbol 
    DecimalSeparator := '.'; 

    if firsttimecall then 
    begin 
    firsttimecall := false; 

    helper := Thelper.Create(); 
    helper.IdTCPServer := TIdTCPServer.Create(nil); 
    helper.IdTCPServer.OnExecute := helper.IdTCPServer1Execute; 
    helper.IdTCPServer.OnConnect := helper.IdTCPServer1Connect; 
    helper.IdTCPServer.OnDisconnect := helper.IdTCPServer1DisConnect; 
    helper.IdTCPServer.DefaultPort := 1239; 
    try 
     helper.IdTCPServer.Active := true; 
     if helper.IdTCPServer.Active then 
     Writeln('TCP/IP host ready, default port: '+IntToStr(helper.IdTCPServer.DefaultPort)); 
    except 
     Writeln('*** Could not start TCP/IP server ***'); 
    end; 
    end; 

    st := IntToStr(nInputs)+';'; for i:=1 to nInputs do st := st + FloatToStr(inputvector[i])+';'; 
    server_lastread := ''; 
    server_to_be_send := st; 

    while (server_lastread='') do Application.ProcessMessages(); 

    st := server_lastread; 
    server_lastread := ''; 

    for i:=1 to nOutputs do 
    begin 
    if Length(st) < 1 then 
    begin 
     outputvector[i] := 0; 
    end 
    else 
    begin 
     outputvector[i] := StrToFloat(copy(st,1,AnsiPos(';',st)-1)); 
     st := copy(st,AnsiPos(';',st)+1,MaxInt); 
    end; 
    end; 
end; 

// Only call tcplink when time has changed 
Procedure tcplink_delay(na:integer;var inputvector : array_in; 
        nb:integer;var outputvector: array_out);stdcall; 
var 
    i : Integer; 
begin 
    if inputvector[1] > time_old then 
    begin 
    tcplink(na, inputvector_delay, nb, outputvector_delay); 
    time_old := inputvector[1]; 
    end; 

    for i :=1 to nInputs do inputvector_delay[i] := inputvector[i]; 
    for i :=1 to nOutputs do outputvector[i] := outputvector_delay[i]; 

end; 

Procedure tcplink_init(var string256:ts; length:integer);stdcall; 
var 
    init_str : string[255]; 
    onPos : Integer; 
begin 
    init_str:=strpas(string256); 
    // Crop trailing blanks 
    onPos := AnsiPos(' ', init_str); 
    SetLength(init_str, onPos-1); 

    if firsttimecall then 
    begin 
    firsttimecall := false; 

    helper := Thelper.Create(); 
    helper.IdTCPServer := TIdTCPServer.Create(nil); 
    helper.IdTCPServer.OnExecute := helper.IdTCPServer1Execute; 
    helper.IdTCPServer.OnConnect := helper.IdTCPServer1Connect; 
    helper.IdTCPServer.OnDisconnect := helper.IdTCPServer1DisConnect; 
    helper.IdTCPServer.DefaultPort := StrToInt(init_str); 

    try 
     helper.IdTCPServer.Active := true; 
     if helper.IdTCPServer.Active then 

     Writeln('TCP/IP host ready, selected port: '+IntToStr(helper.IdTCPServer.DefaultPort)); 
    except 
     Writeln('*** Could not start TCP/IP server ***'); 
    end; 
    end; 

end; 

Procedure tcplink_delay_init(var string256:ts; length:integer);stdcall; 

begin 
    tcplink_init(string256, length); 
end; 

exports 
    tcplink, tcplink_delay, tcplink_init, tcplink_delay_init; 

begin 
end. 
+2

如果您知道這是您可能會給出解決方案的原因(https://www.google.com/search?q=+ Indy + 10 + 9 + TIdPeerThread) – 2015-02-11 11:06:52

+0

恩,感謝您的快速回復!我已經嘗試過了:) 實際上,我從'TIdPeerThread'切換到'TIdContext',並在代碼中使用了'AContext'而不是'AThread'。我還必須將'AThread.Connection.WriteLn'更改爲'AContext.Connection.iohandler.WriteLn'。 現在的代碼編譯,但不起作用!這裏的任何幫助非常感謝! – Mahmood 2015-02-11 12:23:00

+0

請描述'不起作用'。什麼錯誤?你在調試器中看到什麼值返回?你可能不是Delphi程序員,但是你將不得不學習IDE,因爲我們不能爲你調試;-)如果你編輯你的問題,並且把修改後的Indy10部分放在Indy9的。 – 2015-02-11 12:44:35

回答

1

正如你提到的,原代碼爲印第安納波利斯9寫成的,所以需要更新到印第安納波利斯10

它也出現了德爾福的預Unicode版本已經被寫入。 tsChar的數組,它是Delphi 2007及更早版本中的AnsiChar和Delphi 2009及更高版本中的WideChar。 Indy 9不支持Delphi的Unicode版本。所以我會假設Char在這種情況下打算是AnsiChar

也有一些小的邏輯問題。

下面是一個印10版,有一些額外的修復/調整:

library TCPServer; 

uses 
    SysUtils, 
    Classes, 
    Forms, 
    IdContext, 
    IdTCPServer, 
    Dialogs; 

{$R *.res} 

const 
    nInputs = 60; 
    nOutputs = 60; 

type 
    ts = array[0..255] of AnsiChar; 
    array_in = array[1..nInputs] of Single; 
    array_out = array[1..nOutputs] of Single; 

    Thelper = class 
    IdTCPServer: TIdTCPServer; 
    destructor Destroy; override; 
    procedure IdTCPServer1Execute(AContext: TIdContext); 
    procedure IdTCPServer1Connect(AContext: TIdContext); 
    procedure IdTCPServer1DisConnect(AContext: TIdContext); 
    end; 

var 
    helper: Thelper = nil; 

    server_to_be_send: string = ''; 
    server_lastread: string = ''; 

    inputvector_delay : array_in; 
    outputvector_delay : array_out; 
    time_old : single = -1.0; 

destructor Thelper.Destroy; 
begin 
    IdTCPServer.Active := false; 
    IdTCPServer.Free; 
    inherited; 
end; 

procedure Thelper.IdTCPServer1Connect(AContext: TIdContext); 
var 
    s: string; 
begin 
    s := Format('Connect on %s:%d (peer %s:%d)', [AContext.Binding.IP, AContext.Binding.Port, AContext.Binding.PeerIP, AContext.Binding.PeerPort]); 
    WriteLn(s); 
end; 

procedure Thelper.IdTCPServer1DisConnect(AContext: TIdContext); 
var 
    s: string; 
begin 
    s := Format('Disconnect from %s:%d (peer %s:%d)', [AContext.Binding.IP, AContext.Binding.Port, AContext.Binding.PeerIP, AContext.Binding.PeerPort]); 
    WriteLn(s); 
end; 

procedure Thelper.IdTCPServer1Execute(AContext: TIdContext); 
var 
    ii : Integer; 
    s : string; 
begin 
    if (server_to_be_send <> '') then 
    begin 
    try 
     AContext.Connection.IOHandler.WriteLn(server_to_be_send); 
    finally 
     server_to_be_send := ''; 
    end; 
    s := AContext.Connection.IOHandler.ReadLn('*', 5000); 
    if s = '' then 
    begin 
     for ii := 1 to nInputs do 
     s := s + '0;'; 
    end; 
    server_lastread := s; 
    end else begin 
    Sleep(10); 
    end; 
end; 

procedure tcplink(na: Integer; var inputvector: array_in; 
        nb: Integer; var outputvector: array_out); stdcall; 
var 
    i : Integer; 
    st : string; 
    t: Cardinal; 
begin 
    if helper = nil then 
    begin 
    helper := Thelper.Create; 
    helper.IdTCPServer := TIdTCPServer.Create(nil); 
    helper.IdTCPServer.OnExecute := helper.IdTCPServer1Execute; 
    helper.IdTCPServer.OnConnect := helper.IdTCPServer1Connect; 
    helper.IdTCPServer.OnDisconnect := helper.IdTCPServer1DisConnect; 
    helper.IdTCPServer.DefaultPort := 1239; 
    helper.IdTCPServer.MaxConnections := 1; 
    end; 
    if not helper.IdTCPServer.Active then 
    try 
    helper.IdTCPServer.Active := true; 
    Writeln('TCP/IP host ready, default port: '+IntToStr(helper.IdTCPServer.DefaultPort)); 
    except 
    Writeln('*** Could not start TCP/IP server ***'); 
    Exit; 
    end; 

    st := IntToStr(nInputs)+';'; 
    for i:=1 to nInputs do st := st + FloatToStr(inputvector[i])+';'; 
    server_lastread := ''; 
    server_to_be_send := st; 

    t := Ticks; 
    while (server_lastread = '') and (GetTickDiff(t, Ticks) < 10000) do 
    Application.ProcessMessages; 

    st := server_lastread; 
    server_lastread := ''; 

    for I := 1 to nOutputs do 
    begin 
    if Length(st) < 1 then begin 
     outputvector[i] := 0; 
    end else 
    begin 
     outputvector[i] := StrToFloat(Copy(st,1,Pos(';',st)-1)); 
     st := Copy(st,Pos(';',st)+1,MaxInt); 
    end; 
    end; 
end; 

// Only call tcplink when time has changed 
procedure tcplink_delay(na: Integer; var inputvector : array_in; 
         nb: Integer; var outputvector: array_out); stdcall; 
var 
    i : Integer; 
begin 
    if inputvector[1] > time_old then 
    begin 
    tcplink(na, inputvector_delay, nb, outputvector_delay); 
    time_old := inputvector[1]; 
    end; 

    for i :=1 to nInputs do inputvector_delay[i] := inputvector[i]; 
    for i :=1 to nOutputs do outputvector[i] := outputvector_delay[i]; 
end; 

procedure tcplink_init(var string256: ts; length: Integer); stdcall; 
var 
    init_str : string; 
    onPos : Integer; 
begin 
    init_str := strpas(string256); 
    // Crop trailing blanks 
    onPos := Pos(' ', init_str); 
    SetLength(init_str, onPos-1); 

    if helper = nil then 
    begin 
    helper := Thelper.Create; 
    helper.IdTCPServer := TIdTCPServer.Create(nil); 
    helper.IdTCPServer.OnExecute := helper.IdTCPServer1Execute; 
    helper.IdTCPServer.OnConnect := helper.IdTCPServer1Connect; 
    helper.IdTCPServer.OnDisconnect := helper.IdTCPServer1DisConnect; 
    helper.IdTCPServer.MaxConnections := 1; 
    end; 
    if not helper.IdTCPServer.Active then 
    try 
    helper.IdTCPServer.DefaultPort := StrToInt(init_str); 
    helper.IdTCPServer.Active := true; 
    Writeln('TCP/IP host ready, selected port: '+IntToStr(helper.IdTCPServer.DefaultPort)); 
    except 
    Writeln('*** Could not start TCP/IP server ***'); 
    Exit; 
    end; 
end; 

procedure tcplink_delay_init(var string256: ts; length: Integer); stdcall; 
begin 
    tcplink_init(string256, length); 
end; 

procedure tcplink_cleanup; stdcall; 
begin 
    FreeAndNil(helper); 
end; 

exports 
    tcplink, tcplink_delay, tcplink_init, tcplink_delay_init, tcplink_cleanup; 

begin 
    // Ensure English locale decimal separator symbol 
    FormatSettings.DecimalSeparator := '.'; 
end. 

如此說來,由於原代碼出現到被設計用於一次單一的TCP連接,並tcplink()發送命令並等待回覆,則可能會重新編寫代碼以使用TIdSimpleServer而不是TIdTCPServer。與TIdTCPServer不同,TIdSimpleServer不是多線程組件,所以它會允許tcplink()更具自包含性和線性:等待連接,發送命令,讀取回復,完成。無需全局字符串變量,事件處理程序,繁忙的等待等。

+0

完美!非常感謝雷米!有用! – Mahmood 2015-02-12 09:24:32

+0

然後請將答案標記爲已接受。 – 2015-02-12 17:12:14

+0

新手錯誤! :) – Mahmood 2015-02-12 17:53:35