源码
library sdata;uses
  windows,
  SysUtils,
  Classes,
  uClient in 'uClient.pas' {FClient};exports
     ClientSendFile name 'ClientSendFile',//dll入口
     ClientLoadFile name 'ClientLoadFile',
begin
end.
***********************************************************
uClient.pas如下unit uClient;interfaceuses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ScktComp, ComCtrls, StdCtrls, ExtCtrls, Registry;type
  TFClient = class(TForm)
    ClientSocket1: TClientSocket;{ 不用在设计时初始化相关属性,在程序中设置 }
    ProgressBar1: TProgressBar;{ 用于显示数据传输进度 }
    ButtonCancel: TButton;{ 取消数据传输 }
    Label1: TLabel;{ 用于动态显示传输数据完成的百分比 }
    procedure ButtonCancelClick(Sender: TObject);{ 事件:按“取消”按钮 }
    procedure ClientSocket1Connect(Sender: TObject;{ 事件:建立连接 }
      Socket: TCustomWinSocket);
    procedure ClientSocket1Connecting(Sender: TObject;{ 事件:正在连接 }
      Socket: TCustomWinSocket);
    procedure ClientSocket1Disconnect(Sender: TObject;{ 事件:断开连接 }
      Socket: TCustomWinSocket);
    procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);{ 事件:读取数据}
    procedure FormDestroy(Sender: TObject);{ 事件:销毁窗体 }
  private
    { Private declarations }
    procedure DoFirstVerb(AVerb: Integer); { 私有方法:发出第一个命令(动词) }
  public
    { Public declarations }
  end;  function  ClientSendFile(LocalSrcFileName: string;
            IP: string = '127.0.0.1'): Boolean;export;implementationuses
  uSocketCommon;{ 引用公共的单元,该单元中包括Socket的一些例程 }var
  FPort: Integer = ServerSocketPort;{ 用于存取端口号,等号右边的常量在单元uSocketCommon 中有声明 }
  FirstVerb: Integer;   { 用于存取数据传输任务的第一个动词命令 }
  NeedFree: Boolean = False;  { 用于存取是否需要将进度窗体销毁 }{$R *.dfm}function  ClientSendFile(LocalSrcFileName: string;
                         IP: string = '127.0.0.1'): Boolean;export;{ 向服务器端发送 }
var
  P: PSocketData; { 存取Socket的相关信息,类型指针PSocketData在单元uSocketCommon中声明 }
begin
  with TFClient.Create(Application) do try{ 即用即创建 }
      NeedFree := False;{ 初始值,不用程序自动销毁 }
    ClientSocket1.Address := IP;{ 设置服务器端的IP地址 }
    ClientSocket1.Port := FPort;{ 设置端口号           }
    P := NewSocketData;         { 新建类型指针,函数NewSocketData在公共单元中 }
    P^.ProgressBar := ProgressBar1;{ 为P指定进度条 }
    P^.ALabel := Label1;           { 为P指定标签   }
    ClientSocket1.Socket.Data := P;{ 指定当前Socket的相关信息 }
    try
      ClientSocket1.Active := True;{ 试图建立连接  }
    except
      ShowError(Application.Handle, sConnectError);{ 连接失败,报告信息 }
      NeedFree := True;{ 需要程序自动销毁进度窗体 }
    end;
    if not NeedFree then begin{ 连接成功则保存发送文件的相关信息 }
      P := ClientSocket1.Socket.Data;
      P^.SrcFileName := LocalSrcFileName;
      P^.DstFileName := ExtractFileName(LocalSrcFileName);
      FirstVerb := vcSave;{ 设置第一个动词是vcSave,动词声明在公共单元中 }
      Result := ShowModal = mrOK;{ 显示数据传输进度窗体 }
    end else begin{ 连接失败 }
      Result := False;
    end;
  finally
    Free;{ 用完即销毁 }
  end; 
end;procedure TFClient.ButtonCancelClick(Sender: TObject);{ 取消传输 }
var
  SendBuf: TSendBuf;
  P: PSocketData;
  AVerb: TSocketVerb;
  L: Integer;
begin
  P := ClientSocket1.Socket.Data;{ 获得当前数据 }
  if (P <> nil) and P^.OnLine then begin { 根据合适的状态进行取消的动作 }
    AVerb := vcCancel;{ 动词是客户端请求取消 }
    MakeVerbBuf(AVerb, SendBuf, L);{根据动词生成发送的数据}
    ClientSocket1.Socket.SendBuf(SendBuf, LeadLen);{发送请求取消数据包}
  end else begin { 否则直接销毁窗口 }
    ModalResult := mrCancel;
  end;
end;
procedure TFClient.ClientSocket1Connect(Sender: TObject;
  Socket: TCustomWinSocket); {连接成功时即刻发出第一个动词 }
var
  P: PSocketData;
begin
  Label1.Caption := '';        { 标签设计时的文本是“连接失败,请[取消]” }
  Label1.Font.Color := clBlack;{ 设计时字体颜色是红色,连接成功后置为黑色 }
  Caption := sConnectedOK;     { 连接成功 }
  P := ClientSocket1.Socket.Data; { 获得数据地址 }
  if P <> nil then begin
    P^.OnLine := True;     { 置连接状态为True }
    DoFirstVerb(FirstVerb);{ 发出第一个动词 }
    if FirstVerb = vcSave then{ 根据第一个动词确定窗体的标题 }
      Caption := sSaving
    else
      Caption := sLoading;
  end;
end;
procedure TFClient.ClientSocket1Connecting(Sender: TObject;
  Socket: TCustomWinSocket);{ 正在连接时的处理 }
begin
        Caption := sConnecting;{ 显示正在连接的信息 }
end;procedure TFClient.ClientSocket1Disconnect(Sender: TObject;
  Socket: TCustomWinSocket);{ 断开连接时的处理 }
var
  P: PSocketData;
begin
  Caption := sDisconnectedOK;{ 显示相关信息在标题 }
  P := ClientSocket1.Socket.Data;{ 获取数据 }
  ResetSocketData(P);{ 释放有关的资源,如关闭文件、流等 }
  if P <> nil then P^.OnLine := False;{ 置连接状态为False }
end;{ 下面对事件OnRead的处理是客户端应用程序的关键所在,该事件与服务器程序中的相应
  事件互相接收和发送,并且严格遵循“你一句我一句”的原则,这样的循环控制才使得
  数据传输能够快速有序地进行。应答序列的开始是客户端应用程序在ClientSocket连接
  成功时发出的第一个动词引起的。 }
procedure TFClient.ClientSocket1Read(Sender: TObject;
  Socket: TCustomWinSocket);
var
  LeadBuf: TLeadBuf;{具有固定长度的引导包,引导包的作用是正确识别合法用户}
  DataBuf: TDataBuf;{数据包}
  GetBuf, SendBuf: TSendBuf;{接收包和发送包}
  Len, SendSize, Verb: Integer;
  P: PSocketData;
begin
  Len := ClientSocket1.Socket.ReceiveBuf(GetBuf, SendLen);  { 将接收到的包读到
                    GetBuf中,并将实际读取的字节数存入Len中,这里的参数SendLen
                    用于指定最多读取的字节数,在公共单元中声明 }
  Verb := vsNone;{初始得到的动词值}
  if Len >= LeadLen then begin{如果实际字节数大于等于引导包的字节数,则初步认定
                               可以对该数据包进行分析}
    ExtractBuf(GetBuf, Len, LeadBuf, DataBuf);{将得到的包分离出引导包和数据包}
    Verb := ExtractVerb(LeadBuf);{根据引导包分析出包的动词}
    ClientEchoForVerb(Verb, DataBuf, Len - LeadLen,
                      SendBuf, SendSize, ClientSocket1);{对服务器端动词的响应,
                                                最后生成一个响应的包,即应答包}
    case Verb of
      vsEchoCancel: ModalResult := mrCancel;{如果动词是响应取消,则释放窗体}
      vsFail,
      vsEchoFail,
      vsNone:       ModalResult := mrAbort;{如果动词非法,则释放窗体}
      vsSaveOK,
      vsLoadOK:     ModalResult := mrOK;{如果动词是成功结束,则释放窗体}
    else
    end;
  end else begin{如果得到的包的字节数小于引导包指定的字节数,则认为是非法包}
    SendSize := 0;{不需要响应}
  end;
  if SendSize > 0 then
    ClientSocket1.Socket.SendBuf(SendBuf, SendSize);{发送应答包}
  if IsTerminateVerb(Verb) then begin{如果是需要终止的动词,那么重置相关数据}
    P := Socket.Data;
    ResetSocketData(P);
  end;
end;
procedure TFClient.FormDestroy(Sender: TObject);{ 销毁窗体时释放资源 }
var
  P: PSocketData;
begin
  P := ClientSocket1.Socket.Data;
  ClientSocket1.Socket.Data := nil;
  Dispose(P);
end;procedure TFClient.DoFirstVerb(AVerb: Integer);{私有方法}
var
  SendBuf: TSendBuf;
  L: Integer;
begin
  MakeVerbBuf(AVerb, SendBuf, L);{生成第一个动词的数据包}
  ClientSocket1.Socket.SendBuf(SendBuf, LeadLen);{发送该数据包}
end;
end.

解决方案 »

  1.   

    是不是dll的参数传抵方式有错误 传抵方式共有4种你试试看
      

  2.   

    对哦,好像是吧,pb是不是和c一样?要用通用的参数!比如pchar
      

  3.   

    加入stdcallstring改为pchar我也是delphi + pb交流一下[email protected]
      

  4.   

    PB不支持string,建议改为Pchar
    函数采用Stdcall传递参数
    cdecl:通常是C、C++所使用的参数传递方式,由右到左,而且当被调用的函数结束之后,将会调用函数本身来清除堆栈上的参数数据
    Stdcall:通常是C、C++所使用的参数传递方式,由,右到左,而且当被调用的函数结束之后,将会由被调用函数来清除堆栈上的参数数据,Win32 API 所有的输出函数都采用此传递方式。