红色部分改动后,原来的E2009 Incompatible types : 'method pointer and regular procedure' 错误提示没了,可串口接收事件根本不激活。即使定时查询串口也读不到任何数据。部分主要代码,贴出如下:
为什么?请各位高手帮帮忙。谢谢。分数有限,只能将所有分都拿出来了,别嫌少。library ComPortDLL;uses
  ShareMem, SysUtils, CPort, Windows, Classes;type
  TABC=class(TComponent)
    procedure CommPortRxChar(Sender:TObject; Count: Integer);
  end;
{$R *.res}
var
  ABC : TABC;
  CommPort : TComPort;
  DataReadFromCommPort : string;
  
procedure TABC.CommPortRxChar(Sender: TObject; Count: Integer);
var ByteReaded,temp : integer;
    strReaded : String;
begin
  ByteReaded := CommPort.ReadStr(strReaded,count);
  DataReadFromCommPort := DataReadFromCommPort+strReaded;
  while ByteReaded<Count do begin
    temp := CommPort.ReadStr(strReaded,Count-ByteReaded);
    if temp>0 then begin
      ByteReaded := ByteReaded + temp;
      DataReadFromCommPort := DataReadFromCommPort+strReaded;
    end;
  end;
end;procedure InitStatus();
begin
  DataReadFromCommPort := '';
end;//打开串口
function OpenSerialPort(uPort, tBaudRate : integer) : boolean; stdcall;
begin
  if (CommPort<>nil) then begin
    CommPort.Close;
    CommPort.Destroy;
  end;  CommPort := TComPort.Create(nil);
  CommPort.Port := 'COM'+IntToStr(uPort);
  case tBaudRate of
    0: CommPort.BaudRate := br300;
    1: CommPort.BaudRate := br600;
    2: CommPort.BaudRate := br1200;
    3: CommPort.BaudRate := br2400;
    4: CommPort.BaudRate := br4800;
    5: CommPort.BaudRate := br9600;
    6: CommPort.BaudRate := br14400;
    7: CommPort.BaudRate := br19200;
    8: CommPort.BaudRate := br38400;
    9: CommPort.BaudRate := br56000;
    10: CommPort.BaudRate := br57600;
    11: CommPort.BaudRate := br115200;
  end;
  CommPort.DataBits := dbEight;
  CommPort.StopBits := sbOneStopBit;
  CommPort.SyncMethod := smWindowSync;
  CommPort.OnRxChar := ABC.CommPortRxChar;
  CommPort.Open;
  Result := CommPort.Connected;
end;//关闭串口
procedure StopCom(); stdcall;
begin
  if (CommPort<>nil) then begin
    CommPort.Close;
    CommPort.Destroy;
  end;
  CommPort := nil;
end;//发送 AT 指令
function SendComCommand(sendStr : String) : integer; stdcall;
begin
  Result := 0;
  if ((CommPort.Connected) and (sendStr<>'')) then begin
    Result := CommPort.WriteStr(sendStr+#$D);
  end;
end;Exports
  OpenSerialPort, StopCom, SendComCommand;begin
  InitStatus;
  ABC := TABC.Create(nil);
end.

解决方案 »

  1.   

    library cPort_DLL;uses
      SysUtils,
      Classes,
      Frm_cPort in 'Frm_cPort.pas';{$R *.res}exports  SetCallback,
      OpenPort,
      ClosePort,
      WriteStr;begin
    end.//////////////////////////////////////////////////////////////////////////////////////////////////unit Frm_cPort;interfaceuses
      Windows, SysUtils, CPort, CPortCtl;type
      TCallback = procedure(s: pchar); stdcall;   //回调  TMy_cPort_OBJ= class
        procedure My_cPortRxChar(Sender: TObject; Count: Integer);
      end;  var
        My_cPort: TComPort;
        My_cPort_OBJ: TMy_cPort_OBJ;
        FCallback: TCallback;       //回调    function WriteStr(SD: string): integer; stdcall;
        procedure SetCallback(ACallback: TCallback); stdcall;   //回调
        
        function OpenPort(Port: shortstring; BTL: integer): integer; stdcall;
        function ClosePort: integer; stdcall;
    implementation
    procedure INI_cPort;
    begin
      My_cPort := TComPort.Create(nil);
      My_cPort.OnRxChar := My_cPort_OBJ.My_cPortRxChar;
    end;procedure FREE_cPort;
    begin
      try
        if My_cPort_OBJ <> nil then
        begin
          My_cPort_OBJ.FREE;
          My_cPort_OBJ := nil;
        end;    if My_cPort <> nil then
        begin
          My_cPort.FREE;
          My_cPort := nil;
        end;
      except
      end;
    end;procedure SetCallback(ACallback: TCallback); stdcall;
    begin
      FCallback := ACallback;
    end;
    procedure TMy_cPort_OBJ.My_cPortRxChar(Sender: TObject; Count: Integer);   //接收
    var
      Str: string; 
    begin
      My_cPort.ReadStr(Str, Count);
      if Assigned(FCallback) then
       FCallback(pchar(Str));
    end;
    function WriteStr(SD: string): INTEGER; stdcall;        //发送
    begin
      My_cPort.WriteStr(SD);
    end;
    function OpenPort(Port: shortstring; BTL: INTEGER): INTEGER; stdcall;
    begin
      INI_cPort;  My_cPort.Port := 'com' + Port;
      My_cPort.BaudRate := br9600;  //BTL自行修改    //TBaudRate = (brCustom, br110, br300, br600, br1200, br2400, br4800, br9600, br14400,
        //br19200, br38400, br56000, br57600, br115200, br128000, br256000);
        
      //My_cPort.StopBits :=
      //My_cPort.DataBits :=
      //My_cPort.Buffer := 
      try
        My_cPort.Connected := true;
        RESULT := 1;
      except
        RESULT := -1;
      end;end;function ClosePort: INTEGER; stdcall;
    begin
      try
        if My_cPort <> nil then
          My_cPort.Connected := false;
        RESULT := 2;
      except
        RESULT := -2;
      end;
      FREE_cPort;
    end;
    initialization
      //CoInitialize(nil);
    finalization
      //CoUninitialize;end.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    DEMO程序
    unit FrmMain;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;type
      TCallback = procedure(s: pchar); stdcall;var
      Form1: TForm1;function OpenPort(PORT: shortstring; BTL: integer): integer; stdcall External 'cPort_DLL.dll';
    function ClosePort: integer; stdcall External 'cPort_DLL.dll';
    function WriteStr(SD: string): integer; stdcall External 'cPort_DLL.dll';
    procedure SetCallback(ACallback: TCallback); stdcall External 'cPort_DLL.dll';
    procedure CallbackExample(s: pchar); stdcall;implementation{$R *.dfm}procedure CallbackExample(s: pchar); stdcall;
    begin
      Form1.Memo1.Text := Form1.Memo1.Text + ' ' + (s);
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      OpenPort('1',9600);
      SetCallback(@CallbackExample); //设置回调
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      ClosePort;
    end;procedure TForm1.Button3Click(Sender: TObject);
    begin
       WriteStr('hello');
    end;end.
      

  2.   

    DLL里面控件的事件要用回调函数传回给主函数。
    主函数不能直接CommPort := TComPort.Create(nil); 
      

  3.   

    OpenPort里面你看看里面有些什么设置,我没有用过cport。多少个字节触发RxChar事件我没有设置。我也没有仔细看cport说明。
      

  4.   

    这种用法在Form和Thread中已用过,一点问题也没有,但到了DLL中就不行。
      

  5.   

    可能是cport事件和spcomm等不太一样,要看看代码再说。
    spcomm这样没有问题的
      

  6.   

    //经测试可用
    //CPort.SyncMethod := smNone;  call events inside monitoring thread;可行//;  
    //CPort.SyncMethod := smThreadSync; call events in main thread 不可行 DoEvents执行不了,应该是主程序调用DLL,DLL里面再操作TComThread出的问题。
    function OpenPort(Port: shortstring; BTL: Integer): Integer; stdcall;
    begin
      INI_cPort;  CPort.BeginUpdate;
      CPort.Port := 'com3';
      CPort.BaudRate := br115200; //BTL自行修改  CPort.DataBits := dbEight;
      CPort.StopBits := sbOneStopBit;
      CPort.Parity.Bits := prNone;
      CPort.FlowControl.FlowControl := fcNone;
      CPort.SyncMethod := smNone;//smThreadSync; //此处注意  
      CPort.EndUpdate;  try
        CPort.Open;
        RESULT := 1;
      except
        RESULT := -1;
      end;end;
      

  7.   

    DLL中使用Synchronize有这个问题,要是不想在TComThread线程中操作RxChar就发消息给主程序,让主程序处理,要改动一下cport的代码了
      

  8.   

    dll消息处理和form不一样,自己不会CheckSynchronize; 
    不过可以手动添加,可以看看Delphi中DLL的消息处理和DLL 线程同步问题方面的东西。
    给你一个链接 http://explorer.javaeye.com/blog/106033
      

  9.   

    CPort.SyncMethod := smNone我好像已经试过了,好像不行,再试试。
    http://explorer.javaeye.com/blog/106033我仔细学习一下。
    感谢,试过之后再请教。
      

  10.   

    to oosmile: 
    道理是明白了,但具体操作不懂。
    CommPort.SyncMethod := smWindowSync; 应该是解决这个问题的办法,我从dinglinger的帖子中学到的,为什么到我这里不行,还请再详细指点一下。
    谢谢。
      

  11.   

    to oosmile:
    现在遇到的问题是CPort的发送数据没问题,但OnRXChar事件不能激活,就是这部分。 
    procedure TMy_cPort_OBJ.My_cPortRxChar(Sender: TObject; Count: Integer); //接收 
    var 
    Str: string; 
    begin 
      My_cPort.ReadStr(Str, Count); 
      if Assigned(FCallback) then 
        FCallback(pchar(Str)); 
    end; 
    为什么CPort不行,而同样是动态生成的Timer的OnTimer事件却可以?但在OnTimer事件中手动也收不到任何接收数据?是不是在DLL中CPort就收不到数据。 
      

  12.   

    My_cPort.SyncMethod := smNone;这样就好了
    不使用Synchronize就可以了
      

  13.   

    邮箱 [email protected] 
    测试环境是 Delphi 2006吗?
    谢了
      

  14.   

    楼主。我下载了一个cport控件不知道怎么用。
    能给个小例子吗。? 
    最好有注释
    mail:[email protected]
      

  15.   

    其实Dll中和其他环境下利用 CPort 的道理一样, oosmile 就是一个高手,你可以参考他在2楼的帖子,只是要注意CommPort.SyncMethod := smWindowSync; ,具体原因你参考一下 dinglinger 小呆的帖子,说的很清楚了http://blog.csdn.net/dinglinger/archive/2008/06/23/2579493.aspx 
      

  16.   

    实在是惭愧,耽误大家和自己的那么多时间。
    折腾这么久,大家的测试都没问题,问题肯定出在自己这边,以前一直是将串口连接在设备上的,重新做了一根串口自环线,一看果然能正常工作,仔细对照了一下设备手册,结果发现自己犯了一个低级错误。
    CPort.FlowControl.FlowControl := fcHardware; 应该是硬件流控。
    非常感谢 oosmile.
      

  17.   


    惭愧~~~我也碰到一样的问题,自己找到了应该是修改SyncMethod属性为smWindowSync,但是修改后无效~~~再三仔细一看。同时支持CPort和SPComm,把代码写到了下面~~~~~晕啊,把代码贴出来,后人有个借鉴。
    procedure CreateComm;
    begin
      {$IFDEF CPORT3}
      if CommPort = nil then
      begin
        CommPort := TComPort.Create(nil);
      end;  CommPort.OnRxBuf := TDummy.OnComPortRxBuf;
      CommPort.TriggersOnRxChar := False;
      {$ELSE}
      if CommPort = nil then
        CommPort := TComm.Create(nil);  CommPort.SyncMethod := smWindowSync; 
      CommPort.OnReceiveData := TDummy.OnReceiveData;
      {$ENDIF}
    end;