我用delphi做好了一个程序,(是一个串口通信的小程序)怎么用delphi把它做成dll文件,我对dll一点都不懂,请大家帮帮忙   谢谢

解决方案 »

  1.   

    晕,用delphi的新建功能,建一个DLL模板。把你的程序放进去,把对外可调用的程序exports然后注意一下参数调用顺序,一般函数后加stdcall
      

  2.   

    建立一个新的应用程序,不过要选择dll模板
    file-new -other-dll wizard,然后同楼上
      

  3.   

    把单元文件打开
    把program unit1 改成 library unit1
    编译一下
      

  4.   

    Delphi做DLL太麻煩,調用更麻煩.
      

  5.   

    用delphi的新建功能,建一个DLL模板。把你的函数和一些过程放进去,(重复性比较高的)把对外可调用的程序exports然后注意一下参数调用顺序,一般函数后加stdcall编译一下,ok
      

  6.   

    用delphi的新建功能,建一个DLL模板。把你的函数和一些过程放进去,(重复性比较高的)把对外可调用的程序exports然后注意一下参数调用顺序,一般函数后加stdcall编译一下,ok
      

  7.   

    我给你源代码,留下你的EMAIL
      

  8.   

    正在学习DLL,谢谢![email protected]
      

  9.   

    用delphi的新建功能,建一个DLL模板。把你的函数和一些过程放进去,(重复性比较高的)把对外可调用的程序exports然后注意一下参数调用顺序,一般函数后加stdcall编译一下
      

  10.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, OleCtrls, MSCommLib_TLB, ExtCtrls, ComCtrls, Buttons;type
      TForm1 = class(TForm)
        GroupBox1: TGroupBox;
        Memo1: TMemo;
        Memo2: TMemo;
        Edit1: TEdit;
        Button1: TButton;
        Label1: TLabel;
        Label2: TLabel;
        Edit2: TEdit;
        GroupBox2: TGroupBox;
        ComboBox3: TComboBox;
        ComboBox4: TComboBox;
        ComboBox5: TComboBox;
        ComboBox6: TComboBox;
        Label5: TLabel;
        Label6: TLabel;
        MSComm1: TMSComm;
        MSComm2: TMSComm;
        Timer1: TTimer;
        CheckBox1: TCheckBox;
        Label9: TLabel;
        Label8: TLabel;
        Label10: TLabel;
        Label7: TLabel;
        RadioGroup1: TRadioGroup;
        RadioGroup2: TRadioGroup;
        StatusBar1: TStatusBar;
        Timer2: TTimer;
        BitBtn1: TBitBtn;
        procedure Button1Click(Sender: TObject);    procedure MSComm2Comm(Sender: TObject);
        procedure MSComm1Comm(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure CheckBox1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure RadioGroup1Click(Sender: TObject);
        procedure RadioGroup2Click(Sender: TObject);
        procedure Timer2Timer(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
       s,s1:integer;
     procedure showform(AHandle: THandle);stdcall;
    // procedure showPanelform(AHandle: THandle;panel :TwinControl);stdcall;
    implementation{$R *.dfm}
    procedure showform(AHandle: THandle);stdcall;
    begin
      Application.handle := AHandle;
      form1 := TForm1.Create(Application);
      try
        form1.ShowModal;
        form1.Free;
        Application.Handle:= 0;
      except
        on e:Exception do
        begin
          form1.Free;
          ShowMessage('Form 1 error '+e.Message);
        end
      end;
    end;
    {procedure showPanelform(AHandle: THandle;panel :TwinControl);stdcall;
    begin
      Application.Handle :=AHandle;
      Form1 :=TForm1.Create(Application);
      try    Form1.ParentWindow :=panel.Handle;
         Form1.Align :=alClient;
         Form1.BorderStyle :=bsNone;
         Form1.Show;
        //DLLForm.Free;
        Application.Handle:= 0;
      except
        on e:Exception do
        begin
           Form1.Free;
          ShowMessage('DLLForm error '+e.Message);
        end
      end;
    end;
     }
    function  open_com(com:Tmscomm;port:integer;setting_str:String):Boolean;stdcall;  //开串口函数
    var hnew:thandle;
    begin
      result:=false;
      hnew:=createfile(pchar('com'+inttostr(port)),generic_read,0,nil,open_existing,file_flag_overlapped,0);  //API函数  测试COM口是否有效
      if hnew=invalid_handle_value then
        Exit;
      CloseHandle(hnew);  com.CommPort:=port;
      com.RTSEnable:=true;
      com.Settings:=setting_str;
      com.RThreshold:=2;
      com.PortOpen:=True;
      result:=True;end;procedure TForm1.Button1Click(Sender: TObject);     //只由MSCOMM1来发送数据
    begin
      if mscomm1.PortOpen then
        begin
          mscomm1.Output:=Edit1.Text;
          memo1.Lines.Add(Edit1.Text);
          s:=Length(Edit1.Text)+s;
          s1:=Length(Edit2.Text)+s1; 
          Statusbar1.Panels[1].Text:=' 发送端口:COM'+inttostr(RadioGroup1.ItemIndex+1)+'  接收端口:COM'+inttostr(RadioGroup2.ItemIndex+1)+'    发送的字节数:'+inttostr(s)+'    接收的字节数'+inttostr(s1);
        end;
    end;procedure TForm1.MSComm2Comm(Sender: TObject);
    var v:string;
     t:dword;
    begin
     if mscomm2.CommEvent=2 then
       begin
         t:=gettickcount;
         while GetTickCount-t<200  do
           application.ProcessMessages;
         v:=mscomm2.Input;
         if trim(v)<>'' then
           begin
             Edit2.Text:=v;
             memo2.Lines.Add(v);
           end;
       end;end;procedure TForm1.MSComm1Comm(Sender: TObject);
    var v:string;
     t:dword;
    begin
     if mscomm1.CommEvent=2 then
       begin
         t:=gettickcount;
         while GetTickCount-t<200  do
           application.ProcessMessages;
          
         v:=mscomm1.Input;
         if trim(v)<>'' then
           begin
          
             Edit2.Text:=v;
             memo2.Lines.Add(v);
           end;
       end;end;procedure TForm1.Timer1Timer(Sender: TObject);
    begin
         Button1Click(self);
    end;procedure TForm1.CheckBox1Click(Sender: TObject);
    begin
         if checkbox1.Checked=true then
          timer1.Enabled:=true
          else
          timer1.Enabled:=false;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
         timer1.Enabled:=false;     
    end;procedure TForm1.RadioGroup1Click(Sender: TObject);
    var speed_string,parity_string,size_string,stop_string:string;
    begin
      if mscomm1.PortOpen then
        mscomm1.PortOpen:=false;
      speed_string:=Combobox3.Text;  case Combobox4.ItemIndex of
      0: parity_string:='n';
      1: parity_string:='e' ;
      4: parity_string:='o';
      end; size_string:=Combobox5.Text;
     stop_string:=Combobox6.Text; speed_string:=speed_string+','+parity_string+','+size_string+','+stop_string;
     if open_com(mscomm1,RadioGroup1.ItemIndex+1,speed_string) then
       begin
         RadioGroup1.Enabled:=false;
         radiogroup2.Enabled:=true;
       end;
    end;procedure TForm1.RadioGroup2Click(Sender: TObject);
    var speed_string,parity_string,size_string,stop_string:string;
    begin
    if mscomm2.PortOpen then
      mscomm2.PortOpen:=false;
      speed_string:=Combobox3.Text;  case Combobox4.ItemIndex of
      0: parity_string:='n';
      1: parity_string:='e' ;
      4: parity_string:='o';
      end; size_string:=Combobox5.Text;
     stop_string:=Combobox6.Text; speed_string:=speed_string+','+parity_string+','+size_string+','+stop_string;
     if open_com(mscomm2,RadioGroup2.ItemIndex+1,speed_string) then
       begin
         RadioGroup2.Enabled:=false;
         button1.Enabled:=true;
         bitbtn1.Enabled:=true;
       end
     else
       if mscomm1.PortOpen then
        begin
         radiogroup2.Enabled:=false;
         button1.Enabled:=true;
       end
       else
         showmessage('开串口失败!');
    end;procedure TForm1.Timer2Timer(Sender: TObject);
    begin
       statusbar1.Panels[2].Text:='当前时间:'+datetimetostr(now());end;procedure TForm1.BitBtn1Click(Sender: TObject);
    begin
        if application.MessageBox('关闭端口会停止数据的传送,是否要关闭端口?','提示',mb_okcancel)=idok then
        begin
         mscomm1.PortOpen:=false;
         mscomm2.PortOpen:=false;
         radiogroup1.ItemIndex:=-1;
         radiogroup2.ItemIndex:=-1;
         radiogroup2.Enabled:=false;
         radiogroup1.Enabled:=true;
         bitbtn1.Enabled:=false;
            Statusbar1.Panels[1].Text:='端口已经关闭! :(';
         
         end;
    end;
      
    end.
    怎么调用呀???
    调用后出错呀
      

  11.   

    library mydll;{ Important note about DLL memory management: ShareMem must be the
      first unit in your library's USES clause AND your project's (select
      Project-View Source) USES clause if your DLL exports any procedures or
      functions that pass strings as parameters or function results. This
      applies to all strings passed to and from your DLL--even those that
      are nested in records and classes. ShareMem is the interface unit to
      the BORLNDMM.DLL shared memory manager, which must be deployed along
      with your DLL. To avoid using BORLNDMM.DLL, pass string information
      using PChar or ShortString parameters. }uses
      SysUtils,
      Classes,
      Unit1 in 'Unit1.pas' {Form1};
        exports
      ShowForm name 'ShowForm';
     // showPanelform name 'showPanelform';{$R *.res}begin
    end.
    我制作的dll有问题么??怎么调用不了呀??
      

  12.   

    unit Unitusedll;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      procedure ShowForm(Handle: THandle)stdcall; 
      external 'mydll.dll' name 'ShowForm';  //调用mydll.dll implementation
    {$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      showform(application.Handle);
    end;end.
    调用这个  出错
      

  13.   

    动态链接库是一个能够被应用程序和其它的DLL调用的过程和函数的集合体,它里面包含的是公共代码或资源。由于DLL代码使用了内存共享技术,在某些地方windows也给了DLL一些更高的权限,因而DLL中可以实现一些一般程序所不能实现的功能,如实现windows的HOOK、ISAPI等。同时,DLL还为不同语言间代码共享提供了一条方便的途径。因而DLL在编程时应用较为广泛,本文将介绍如何在 Delphi 中建立和使用DLL。
    一.DLL 库内存共享机制
    从使用效果看,DLL和unit 很像,它们都可以被别的工程模块所调用,但二者在内部的实现机制上确存在着差别。如果一个程序模块中用uses语句引用了某个unit,编译程序在编译该模块时,便会连同unit一起编译,并把编译后的可执行代码链接到本程序模块中,这就是一个程序模块能够调用所引用unit中过程和函数的原因。当同一个unit被多个工程所引用时,则每个工程中都含有该unit的可执行代码,当含有该unit的多个工程同时执行时,unit的可执行代码会随不同工程而多次被调入内存,造成内存资源的浪费。DLL则不同,它即使被某个工程调用,编译后仍是独立的,也就是说编译后,一个DLL库形成一个单独的可执行文件,而不与任何其它的可执行文件连接在一起,因而DLL库并不从属于某个特定的工程,当多个工程调用同一个DLL库时只有第一个工程把DLL库调入内存,其余工程并不重复调入同一个DLL库到内存,而是到同一个共享内存区读取。并且,DLL的执行代码是在程序运行期间动态调入的,而不是如unit在程序运行时就与整个工程一起调入内存。这样便可消除unit带来的相同代码多处占用内存的弊病。
    二 Delphi中DLL库的建立
     在Delphi环境中,编写一个DLL同编写一个一般的应用程序并没有太大的区别。事实上作为DLL主体的DLL函数的编写,除了在内存、资源的管理上有所不同外,并不需要其它特别的手段。
        一般工程文件的格式为:
      program  工程标题; 
      uses    子句; 
      程序体
      而DLLs工程文件的格式为:
      library 工程标题; 
      uses 子句; 
      exprots 子句; 
      程序体
      它们主要的区别有两点:
      1.一般工程文件的头标用program关键字,而DLL工程文件头标用library 关键字。不同的关键字通知编译器生成不同的可执行文件。用program关键字生成的是.exe文件,而用library关键字生成的是.dll文件;
      2.假如DLL要输出供其它应用程序使用的函数或过程,则必须将这些函数或过程列在exports子句中。而这些函数或过程本身必须用export编译指令进行编译。
    在Delphi主菜单file 中选new...项,在弹出的窗口中双击DLL图标,便会自动给出DLL源模块框架,如下:
    Library project1;
    {...注释...}
    uses
    SysUtils, Classes;
    begin
    end. 
    接下来便可在USES和begin之间加入想在该DLL中实现的过程和函数的定义,并用export和exprots保字把它们引出,以便别的模块引用,在begin和end之间加入初始化代码,初始化代码是用来对DLL变量初始化的。应注意,即便无初始化代码begin与end也不可省略,如下例:
    library minmax;
    function Min(X, Y: Integer): Integer; export;
    begin
    if X < Y then Min := X else Min := Y;
    end;
    function Max(X, Y: Integer): Integer; export;
    begin
    if X > Y then Max := X else Max := Y;
    end;
    exports
    Min index 1,
    Max index 2;
    begin
    end. 
    经编译后,并以minmax.DLL存盘后,一个DLL库文件便形成了。
    三 DLL库的访问
    访问DLL库有两种方式,一种是静态引用,另一种是动态引用。
    用静态引用这种方法装入DLL要做两件事情:为DLL 库创建一个输入单元,以及用USES把输入单元连接到要使用DLL 函数的程序模块中。为DLL库创建的输入单元与普通的单元的区别仅在于:在它的接口处声明的过程、函数,并不在它的实现部分给出真正的实现代码,而是用external关键字把过程、函数的实现细节委托给外部DLL模块。
    external命令的使用语法如下:
    procedure /function 过程/函数名;external DLL模块名;
    下面给出为上面创建的minmax.DLL库写的输入单元源文件testdll .pas,从中可看出输入单元与一般单元的一些差别,代码如下所示:
    unit testdll;
    interface
    uses
    function Min (X, Y: Integer): Integer;
    function Max (X, Y: Integer): Integer; 
    implementation 
    function Min; external ‘minmax.DLL’;
    function Max; external ‘minmax.DLL’;
    end. 
    一个应用程序若想调用minmax.DLL中的函数,只须在其uses语句中加入testdll 单元即可。
     动态装入DLL,要用到Windows的三个API函数。Loadlibrary、Freelibrary和GetprocAddress 。loadlibrary函数用来装入DLL库,其调用格式如下:
    function loadlobrary (DLLfileName:Pchar): THandle:
    当不再需要一个DLL库时,应调用FreeLibrary函数将其释放,以空出宝贵的内存资源,其调用格式如下:
    procedure FreeLibrary (Libmodule:THandle)
    Libmodule 为由LoadLibrary调用得到的DLL库句柄。在用loadlobrary 函数装入某个DLL库和调用FreeLibrary释放该DLL库之间的程序段中, 可以使用该DLL库中的过程和函数,具体使用方法是:用GetprocAddress函数把DLL库中函数的地址传递给程序中某个函数变量,再用该变量实现DLL函数的调用。GetprocAddress函数声名如下,
    function GetprocAddress (Libmodule:THandle:procname:pchar):TFarProc: 
    如下例所示:
    type
    TTimeRec = record
    Second: Integer;
    Minute: Integer;
    Hour: Integer;
    end;
    TGetTime = procedure(var Time: TTimeRec);
    THandle = Integer;
    var
    Time: TTimeRec;
    Handle: THandle;
    GetTime: TGetTime;
    ...
    begin
    Handle := LoadLibrary('DATETIME.DLL');
    if Handle <> 0 then
    begin
    @GetTime := GetProcAddress(Handle, 'GetTime');
    if @GetTime <> nil then
    begin
    GetTime(Time);
    with Time do
    WriteLn('The time is ', Hour, ':', Minute, ':', Second);
    end;
    FreeLibrary(Handle);
    end;
    end;
    在调用动态链接库时应注意, 所需动态链接库须与应用程序在同一目录或Windows System 目录下。
    动态链接库是 Windows下程序组织的一种重要方式,使用动态链接库可以极大地保护用户在不同开发工具、不同时期所做的工作,提高编程效率。