动态连接库内容:
library Project1;{ 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,
  QDialogs,
  Classes,
  ght in 'ght.pas' {ght1};{$R *.res}
procedure ghtdllshow;
begin
//showmessage('OK!');
ght1.Show;
end;
exports ghtdllshow;begin
end.
 
可执行文件:
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementation{$R *.dfm}
procedure ghtdllshow; external 'Project1.dll'procedure TForm1.Button1Click(Sender: TObject);
begin
ghtdllshow;
showmessage('successful!');
end;end.
各位大哥赐教!

解决方案 »

  1.   

    也就是简单一个窗体被包含在一个DLL中!ght1!
    编译没有错误,就是运行有错!
      

  2.   

    欢迎您:flyinger1 可用分:1 总信誉分:100 注销我的登录
      

  3.   

    在函数后面加上 Stdcall;
    procedure ghtdllshow;Stdcall;
      

  4.   

    Delphi环境中编写调用DLL的方法和技巧  
    第一章 为什么要使用动态链接库(DLL) top 
    提起DLL您一定不会陌生,在Windows中有着大量的以DLL为后缀的文件,它们是保证Windows正常运行和维护升级的重要保证。(举个例子,笔者的Win95 System目录下尽有500多个DLL文件。)其实,DLL是一种特殊的可执行文件。说它特殊主要是因为一般它都不能直接运行,需要宿主程序比如*.EXE程序或其他DLL的动态调用才能够使用。简单的说,在通常情况下DLL是经过编译的函数和过程的集合。 
    使用DLL技术主要有以下几个原因: 一、减小可执行文件大小。 
    DLL技术的产生有很大一部分原因是为了减小可执行文件的大小。当操作系统进入Windows时代后,其大小已经达到几十兆乃至几百兆。试想如果还是使用DOS时代的单执行文件体系的话一个可执行文件的大小可能将达到数十兆,这是大家都不能接受的。解决的方法就是采用动态链接技术将一个大的可执行文件分割成许多小的可执行程序。 二、实现资源共享。 
    这里指的资源共享包括很多方面,最多的是内存共享、代码共享等等。早期的程序员经常碰到这样的事情,在不同的编程任务中编写同样的代码。这种方法显然浪费了很多时间,为了解决这个问题人们编写了各种各样的库。但由于编程语言和环境的不同这些库一般都不能通用,而且用户在运行程序时还需要这些库才行,极不方便。DLL的出现就像制定了一个标准一样,使这些库有了统一的规范。这样一来,用不同编程语言的程序员可以方便的使用用别的编程语言编写的DLL。另外,DLL还有一个突出的特点就是在内存中只装载一次,这一点可以节省有限的内存,而且可以同时为多个进程服务。 三、便于维护和升级。 
    细心的朋友可能发现有一些DLL文件是有版本说明的。(查看DLL文件的属性可以看到,但不是每一个DLL文件都有)这是为了便于维护和升级。举个例子吧,早期的Win95中有一个BUG那就是在闰年不能正确显示2月29日这一天。后来,Microsoft发布了一个补丁程序纠正了这个BUG。值得一提的是,我们并没有重装Win95,而是用新版本的DLL代替了旧版本的DLL。(具体是哪一个DLL文件笔者一时想不起来了。)另一个常见的例子是驱动程序的升级。例如,著名的DirectX就多次升级,现在已经发展到了6.0版了。更妙的是,当我们试图安装较低版本的DLL时,系统会给我们提示,避免人为的操作错误。例如我们升级某硬件的驱动程序时,经常碰到Windows提示我们当前安装的驱动程序比原来的驱动程序旧。 四、比较安全。 
    这里说的安全也包括很多方面。比如,DLL文件遭受病毒的侵害机率要比普通的EXE文件低很多。另外,由于是动态链接的,这给一些从事破坏工作的“高手”们多少带来了一些反汇编的困难。 第二章 在Delphi中编写DLL top 注意:在这里笔者假定读者使用的是Delphi 3或Delphi 4开场白说了那么多,总该言归正传了。编写DLL其实也不是一件十分困难的事,只是要注意一些事项就够了。为便于说明,我们先举一个例子。 library Delphi; uses 
    SysUtils, 
    Classes; function TestDll(i:integer):integer;stdcall; 
    begin 
    Result:=i; 
    end; exports 
    TestDll; begin 
    end. 上面的例子是不是很简单?熟悉Delphi的朋友可以看出以上代码和一般的Delphi程序的编写基本是相同的,只是在TestDll函数后多了一个stdcall参数并且用exports语句声明了TestDll函数。只要编译上面的代码,就可以得到一个名为Delphi.dll的动态链接库。现在,让我们来看看有哪些需要注意的地方。 一、在DLL中编写的函数或过程都必须加上stdcall调用参数。在Delphi 1或Delphi 2环境下该调用参数是far。从Delphi 3以后将这个参数变为了stdcall,目的是为了使用标准的Win32参数传递技术来代替优化的register参数。忘记使用stdcall参数是常见的错误,这个错误不会影响DLL的编译和生成,但当调用这个DLL时会发生很严重的错误,导致操作系统的死锁。原因是register参数是Delphi的默认参数。 
      

  5.   

    二、所写的函数和过程应该用exports语句声明为外部函数。 
    正如大家看到的,TestDll函数被声明为一个外部函数。这样做可以使该函数在外部就能看到,具体方法是单激鼠标右键用“快速查看(Quick View)”功能查看该DLL文件。(如果没有“快速查看”选项可以从Windows CD上安装。)TestDll函数会出现在Export Table栏中。另一个很充分的理由是,如果不这样声明,我们编写的函数将不能被调用,这是大家都不愿看到的。 三、当使用了长字符串类型的参数、变量时要引用ShareMem。 
    Delphi中的string类型很强大,我们知道普通的字符串长度最大为256个字符,但Delphi中string类型在默认情况下长度可以达到2G。(对,您没有看错,确实是两兆。)这时,如果您坚持要使用string类型的参数、变量甚至是记录信息时,就要引用ShareMem单元,而且必须是第一个引用的。既在uses语句后是第一个引用的单元。如下例: 
    uses 
    ShareMem, 
    SysUtils, 
    Classes; 
    还有一点,在您的工程文件(*.dpr)中而不是单元文件(*.pas)中也要做同样的工作,这一点Delphi自带的帮助文件没有说清楚,造成了很多误会。不这样做的话,您很有可能付出死机的代价。避免使用string类型的方法是将string类型的参数、变量等声明为Pchar或ShortString(如:s:string[10])类型。同样的问题会出现在当您使用了动态数组时,解决的方法同上所述。 第三章 在Delphi中静态调用DLL top 调用一个DLL比写一个DLL要容易一些。首先给大家介绍的是静态调用方法,稍后将介绍动态调用方法,并就两种方法做一个比较。同样的,我们先举一个静态调用的例子。 unit Unit1; interface uses 
    Windows, Messages, SysUtils, Classes, Graphics, 
    Controls, Forms, Dialogs, StdCtrls; type 
    TForm1 = class(TForm) 
    Edit1: TEdit; 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; var 
    Form1: TForm1; implementation {$R *.DFM} //本行以下代码为我们真正动手写的代码 function TestDll(i:integer):integer;stdcall; 
    external ’Delphi.dll’; procedure TForm1.Button1Click(Sender: TObject); 
    begin 
    Edit1.Text:=IntToStr(TestDll(1)); 
    end; end. 上面的例子中我们在窗体上放置了一个编辑框(Edit)和一个按钮(Button),并且书写了很少的代码来测试我们刚刚编写的Delphi.dll。大家可以看到我们唯一做的工作是将TestDll函数的说明部分放在了implementation中,并且用external语句指定了Delphi.dll的位置。(本例中调用程序和Delphi.dll在同一个目录中。)让人兴奋的是,我们自己编写的TestDll函数很快被Delphi认出来了。您可做这样一个实验:输入“TestDll(”,很快Delphi就会用fly-by提示条提示您应该输入的参数是什么,就像我们使用Delphi中定义的其他函数一样简单。注意事项有以 
    下一些:
      

  6.   


    一、调用参数用stdcall。 
    和前面提到的一样,当引用DLL中的函数和过程时也要使用stdcall参数,原因和前面提到的一样。 二、用external语句指定被调用的DLL文件的路径和名称。 
    正如大家看到的,我们在external语句中指定了所要调用的DLL文件的名称。没有写路径是因为该DLL文件和调用它的主程序在同一目录下。如果该DLL文件在C:\,则我们可将上面的引用语句写为external ’C:\Delphi.dll’。注意文件的后缀.dll必须写上。 三、不能从DLL中调用全局变量。 
    如果我们在DLL中声明了某种全局变量,如:var s:byte 。这样在DLL中s这个全局变量是可以正常使用的,但s不能被调用程序使用,既s不能作为全局变量传递给调用程序。不过在调用程序中声明的变量可以作为参数传递给DLL。 四、被调用的DLL必须存在。 
    这一点很重要,使用静态调用方法时要求所调用的DLL文件以及要调用的函数或过程等等必须存在。如果不存在或指定的路径和文件名不正确的话,运行主程序时系统会提示“启动程序时出错”或“找不到*.dll文件”等运行错误。 第四章 在Delphi中动态调用DLL top 动态调用DLL相对复杂很多,但非常灵活。为了全面的说明该问题,这次我们举一个调用由C++编写的DLL的例子。首先在C++中编译下面的DLL源程序。 #include extern ”C” _declspec(dllexport) 
    int WINAPI TestC(int i) 

    return i; 
    } 编译后生成一个DLL文件,在这里我们称该文件为Cpp.dll,该DLL中只有一个返回整数类型的函数TestC。为了方便说明,我们仍然引用上面的调用程序,只是将原来的Button1Click过程中的语句用下面的代码替换掉了。 procedure TForm1.Button1Click(Sender: TObject); 
    type 
    TIntFunc=function(i:integer):integer;stdcall; 
    var 
    Th:Thandle; 
    Tf:TIntFunc; 
    Tp:TFarProc; 
    begin 
    Th:=LoadLibrary(’Cpp.dll’); {装载DLL} 
    if Th>0 then 
    try 
    Tp:=GetProcAddress(Th,PChar(’TestC’)); 
    if Tp<>nil 
    then begin 
    Tf:=TIntFunc(Tp); 
    Edit1.Text:=IntToStr(Tf(1)); {调用TestC函数} 
    end 
    else 
    ShowMessage(’TestC函数没有找到’); 
    finally 
    FreeLibrary(Th); {释放DLL} 
    end 
    else 
    ShowMessage(’Cpp.dll没有找到’); 
    end; 大家已经看到了,这种动态调用技术很复杂,但只要修改参数,如修改LoadLibrary(’Cpp.dll’)中的DLL名称为’Delphi.dll’就可动态更改所调用的DLL。 一、定义所要调用的函数或过程的类型。 
    在上面的代码中我们定义了一个TIntFunc类型,这是对应我们将要调用的函数TestC的。在其他调用情况下也要做同样的定义工作。并且也要加上stdcall调用参数。 二、释放所调用的DLL。 
    我们用LoadLibrary动态的调用了一个DLL,但要记住必须在使用完后手动地用FreeLibrary将该DLL释放掉,否则该DLL将一直占用内存直到您退出Windows或关机为止。 现在我们来评价一下两种调用DLL的方法的优缺点。静态方法实现简单,易于掌握并且一般来说稍微快一点,也更加安全可靠一些;但是静态方法不能灵活地在运行时装卸所需的DLL,而是在主程序开始运行时就装载指定的DLL直到程序结束时才释放该DLL,另外只有基于编译器和链接器的系统(如Delphi)才可以使用该方法。动态方法较好地解决了静态方法中存在的不足,可以方便地访问DLL中的函数和过程,甚至一些老版本DLL中新添加的函数或过程;但动态方法难以完全掌握,使用时因为不同的函数或过程要定义很多很复杂的类型和调用方法。对于初学者,笔者建议您使用静态方法,待熟练后再使用动态调用方法。 第五章 使用DLL的实用技巧 top 一、编写技巧。 
    1 、为了保证DLL的正确性,可先编写成普通的应用程序的一部分,调试无误后再从主程序中分离出来,编译成DLL。 2 、为了保证DLL的通用性,应该在自己编写的DLL中杜绝出现可视化控件的名称,如:Edit1.Text中的Edit1名称;或者自定义非Windows定义的类型,如某种记录。 3 、为便于调试,每个函数和过程应该尽可能短小精悍,并配合具体详细的注释。 4 、应多利用try-finally来处理可能出现的错误和异常,注意这时要引用SysUtils单元。 5 、尽可能少引用单元以减小DLL的大小,特别是不要引用可视化单元,如Dialogs单元。例如一般情况下,我们可以不引用Classes单元,这样可使编译后的DLL减小大约16Kb。 二、调用技巧。 
    1 、在用静态方法时,可以给被调用的函数或过程更名。在前面提到的C++编写的DLL例子中,如果去掉extern ”C”语句,C++会编译出一些奇怪的函数名,原来的TestC函数会被命名为@TestC$s等等可笑的怪名字,这是由于C++采用了C++ name mangling技术。这个函数名在Delphi中是非法的,我们可以这样解决这个问题: 
    改写引用函数为 
    function TestC(i:integer):integer;stdcall; 
    external ’Cpp.dll’;name ’@TestC$s’; 
    其中name的作用就是重命名。 2 、可把我们编写的DLL放到Windows目录下或者Windows\system目录下。这样做可以在external语句中或LoadLibrary语句中不写路径而只写DLL的名称。但这样做有些不妥,这两个目录下有大量重要的系统DLL,如果您编的DLL与它们重名的话其后果简直不堪设想,况且您的编程技术还不至于达到将自己编写的DLL放到系统目录中的地步吧! 三、调试技巧。 
    1 、我们知道DLL在编写时是不能运行和单步调试的。有一个办法可以,那就是在Run|parameters菜单中设置一个宿主程序。在Local页的Host Application栏中添上宿主程序的名字就可进行单步调试、断点观察和运行了。 2 、添加DLL的版本信息。开场白中提到了版本信息对于DLL是很重要的,如果包含了版本信息,DLL的大小会增加2Kb。增加这么一点空间是值得的。很不幸我们如果直接使用Project|options菜单中Version选项是不行的,这一点Delphi的帮助文件中没有提到,经笔者研究发现,只要加一行代码就可以了。如下例: library Delphi; uses 
    SysUtils, 
    Classes; {$R *.RES} 
    //注意,上面这行代码必须加在这个位置 function TestDll(i:integer):integer;stdcall; 
    begin 
    Result:=i; 
    end; exports 
    TestDll; begin 
    end. 3 、为了避免与别的DLL重名,在给自己编写的DLL起名字的时候最好采用字符数字和下划线混合的方式。如:jl_try16.dll。 4 、如果您原来在Delphi 1或Delphi 2中已经编译了某些DLL的话,您原来编译的DLL是16位的。只要将源代码在新的Delphi 3或Delphi 4环境下重新编译,就可以得到32位的DLL了。 [后记]:除了上面介绍的DLL最常用的使用方法外,DLL还可以用于做资源的载体。例如,在Windows中更改图标就是使用的DLL中的资源。另外,熟练掌握了DLL的设计技术,对使用更为高级的OLE、COM以及ActiveX编程都有很多益处。
      

  7.   

    11111:将窗体设置为最大化,并将其BorderStyle设置为bsNone。
    procedure ShowFrm(sHand: TWinControl);stdcall;
    Var
      DockPos : TRect;
    begin
      if not Assigned(frmdock) then
      begin
        frmdock := Tfrmdock.Create(Application);
        frmdock.ParentWindow := sHand.Handle;
        frmdock.Show;
      end;
    end;
    关闭时调用就行了,祝你好运!!!
    Procedure CloseFrm;stdcall;
    begin
      if Assigned(frmdock) then
        FreeAndNil(frmdock);
    end;
      

  8.   


    22222222222222222222222library Tools;uses
      SysUtils,
      Classes,
      windows,
      forms,
      dialogs,
      MaxAccount in 'MaxAccount.pas' {ComputeTax};{$R *.RES}resourcestring
      S_ErrFormExist='This form has exist!';
      S_ErrCreateForm='The form cause error, please contact Wally!';
    procedure MatchForm(OHandle: THandle);
    begin
      try
        FrmMatch := TFrmMatch.Create(Application);
        FrmMatch.ShowModal;
        FrmMatch.Free;
      except
        FrmMatch.Free;
      end;
    end;procedure InitService(const pAction: Integer; const pArgs: array of const); stdcall;
    begin
      Case pAction of
      4: MatchForm(LongInt(pArgs[0].VAnsiString));
      end;
    end;Exports
      InitService;
    begin
    end.
      

  9.   

    3333333333333333333333333333333333333333333333333333333333333333333333333333333333根据Delphi提供的有关 DLL编写和调用的帮助信息,你可以很快完成一般的 DLL编写和调用的 应用程序。本文介绍的主题是如何编写和调用能够传递各种参数(包括对象实例)的 DLL。例如, 主叫程序传递给 DLL一个ADOConnection 对象示例作为参数, DLL中的函数和过程调用通过该对象 实例访问数据库。   需要明确一些基本概念。对于 DLL,需要在主程序中包含 exports子句,用于向外界提供调用 接口,子句中就是一系列函数或过程的名字。对于主叫方(调用 DLL的应用程序或其它的 DLL), 则需要在调用之前进行外部声明,即external保留字指示的声明。这些是编写 DLL和调用 DLL必须 具备的要素。   另外需要了解Object Pascal 中有关调用协议的内容。在Object Pascal 中,对于过程和函数 有以下五种调用协议:   指示字 参数传递顺序 参数清除者 参数是否使用寄存器 
      register 自左向右 被调例程 是 
      pascal 自左向右 被调例程 否 
      cdecl 自右向左 调用者 否 
      stdcall 自右向左 被调例程 否 
      safecall 自右向左 被调例程 否   这里的指示字就是在声明函数或过程时附加在例程标题之后的保留字,默认为register,即是 唯一使用 CPU寄存器的参数传递方式,也是传递速度最快的方式;   pascal: 调用协议仅用于向后兼容,即向旧的版本兼容; 
      cdecl: 多用于 C和 C++语言编写的例程,也用于需要由调用者清除参数的例程; 
      stdcall: 和safecall主要用于调用Windows API 函数;其中safecall还用于双重接口。 
      在本例中,将使用调用协议cdecl ,因为被调用的 DLL中,使用的数据库连接是由主叫方传递 得到的,并且需要由主叫方处理连接的关闭和销毁。   下面是 DLL完整源程序和主叫程序完整源程序。包括以下四个文件: Project1.DPR {主叫程序} 
    Unit1.PAS {主叫程序单元} 
    Project2.DPR {DLL} 
    Unit2.PAS {DLL单元} 
    {---------- DLL 主程序 Project2.DPR ----------} library Project2;{ 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,
      Unit2 in 'Unit2.pas' {Form1};{$R *.res}{ 下面的语句用于向调用该 DLL的程序提供调用接口 }
    exports
      DoTest; { 过程来自单元Unit2 }begin
    end. 
    {---------- DLL中的单元 Unit2.PAS ----------} unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, ADODB;type
      TForm1 = class(TForm)
        ADOConnection1: TADOConnection;
        Memo1: TMemo;
      private
        { Private declarations }
      public
        { Public declarations }
      end;{ 该过程向外提供 }
    procedure DoTest(H: THandle; { 获得调用者的句柄 }
                     AConn: TADOConnection;{ 获得调用者的数据库连接 }
                     S: string; { 获得一些文本信息 }
                     N: Integer); { 获得一些数值信息 }
    cdecl; { 指定调用协议 }var
      Form1: TForm1;implementation{$R *.dfm}
    //------------------------------------------------------------------------------
    procedure DoTest(H: THandle; AConn: TADOConnection; S: string; N: Integer);
    begin
      Application.Handle := H; { 将过程的句柄赋值为调用者的句柄 }
      { 上面语句的作用在于, DLL的句柄和调用者的句柄相同,在任务栏中就不会各自出现一个任务标题了。 }  with TForm1.Create(Application) do
        try{ 创建窗体 }
          Memo1.Lines.Append('成功调用'); { 显示一行信息 }
          ADOConnection1 := AConn; { 获得数据库连接的实例 }
          Memo1.Lines.Append(
          ADOConnection1.ConnectionString +
          ' - ' + S + ' - ' + IntToStr(N)); { 根据得到的参数显示另一行信息 }
          ShowModal; { 模式化显示窗体 }
        finally
          Free; { 调用结束时销毁窗口 }
        end;
    end;
    //------------------------------------------------------------------------------
    end.
      

  10.   


    {---------- 调用者 Project1.DPR,很普通的工程文件 ----------} 
    program Project1;uses
      Forms,
      Unit1 in 'Unit1.pas' {Form1};{$R *.res}begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.
    {---------- 调用者单元Unit1.PAS ----------} unit Unit1;interfaceuses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    StdCtrls, Db, ADODB;type
      TForm1 = class(TForm)
        ADOConnection1: TADOConnection;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}{ 外部声明必须和 DLL中的参数列表一致,否则会运行时错误 }
    procedure DoTest(H: THandle; { 传递句柄 }
                     AConn: TADOConnection; { 传递数据库连接 }
                     S: string; { 传递文本信息 }
                     N: Integer); { 传递数值信息 }
    cdecl; { 指定调用协议 }external 'Project2.dll';{ 指定过程来源 }//------------------------------------------------------------------------------
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      DoTest(Application.Handle,ADOConnection1,'Call OK',256);
    end;
    //------------------------------------------------------------------------------
    end.
      

  11.   

    444444444444444444444444444444444444444444444444444444444444用vc写的动态连接库编译后,在delphi中调用,有什么要注意的地方?
    比如说参数的顺序什么的!
    大家帮帮忙,小弟万分火急!在Delphi与C++之间实现函数与对象共享 
      Delphi以其独特的面向控件的开发方式、强大的数据库功能以及快速的编译技术,使得它自发布起即格外引人注意。随着Delphi 3提供丰富的Internet应用,Delphi日益成为最重要的软件开发工具之一,它吸引了许多原Visual Basic、Foxpro、dBase甚至C++的程序员,而这些程序员使用Delphi时需要解决的一个重要问题就是怎样利用他们原有的代码。本文将介绍Delphi与C++程序集成的方法,包括:
      Delphi与C++之间函数的共享;
      代码的静态链接和动态链接;
      对象的共享。函数的共享
      在Delphi中调用C++函数与C++调用Delphi函数相当直接,需要注意的是,Delphi 1默认的函数调用方式是Pascal方式,Delphi 2、Delphi 3的默认方式则是优化的cdecl调用方式,即register方式。要在C++与Delphi程序之间实现函数共享,除非有充分的原因,否则应该使用标准系统调用方式,即stdcall方式。为了使C++编译器不将函数标记为"mang led",使Delphi编译器误认为函数是采用cdecl调用方式,应该在C++代码中,以extern "C "说明被共享的函数,如下例所示:原型说明:
    在C++中:
    extern "C" int _stdcall TestFunc();
    在Delphi中:
    function TestFunc:integer; stdcall;
    调用语法:
    在C++中:
    int i=TestFunc();
    在Delphi中:
    var i:integer;

    begin

    i:=TestFunc;

    end;
      共享函数的参数必须是两种语言都支持的变量类型,这是正确传递参数的前提。诸如Delphi的currency、string、set等变量类型,在C++中没有相对应的变量类型,不能被用作共享函数的参数。可以用PChar类型以值参的方式传递字符串指针,这时用户必须注意字符串空间的回收。
      Delphi语言中的变参应被说明成C++中相应变量类型的引用形式,
    如下:
    在Delphi中:
    function TestFunc(var i:integer):integer;
    在C++中:
    int TestFunc(int &i);代码链接
      在Delphi与C++之间实现代码链接可采用静态链接或动态链接的方式。
    1.静态链接方式
      如果C++程序本身的代码量很小,而且无需担心与C运行库会有交互过程,一般可选用静态链接方式,即把Delphi与C++的目标文件(*.OBJ)链接成最终的可执行文件。具体的方法是使用{$L}编译指令,使Delphi编译器自动读取指定目标文件,说明如下:function TestFunc:integer;stdcall;
    {$L TestFunc.OBJ}2.动态链接方式
      如果C++代码已经相当全面或自成一个完整的子系统,代码量很大,或者用到了C运行库,在这种情况下,应该使用动态链接库(DLL)的方式。此时,在两种语言的源代码中应做如下说明:在C++中:
    int stdcall export TestFunc();
    在Delphi中:
    function TestFunc:integer; stdcall;
    external ‘TestFunc.DLL’;对象的共享
      在C++与Delphi之间的对象共享主要体现在对象方法(Method)的共享方面,这种共享可分为两个层次:对象(Object)级共享与类(Class)级共享。要实现对象级共享,程序设计语言需具备两个前提条件:
      能够定义指向由另一语言创建的对象的指针;
      可以访问由指针确定的对象中的方法。
    要实现类级的共享,则还需考虑:
      能够创建由另一种语言定义的类的实例;
      可以从堆中释放一个实例所占用的空间;
      派生新的类。以下介绍在Delphi与Borland C++之间实现对象共享的方法。
    1.C++共享Delphi对象
      要实现从C++调用Delphi对象,首先要在Delphi单元的接口部分以及C++的头文件中说明需要共享的对象的接口,在对象接口中定义该对象包含哪些属性与方法,并说明可供共享的部分。对象的共享,关键在于方法的共享。在Delphi语言中,要使一个对象可以被共享,可以把它说明为两个接口部分,暂称为"共享接口"与"实现接口"。其中共享接口指明对象中哪些方法可被另一种语言所共享;实现接口则继承共享接口,并且在单元实现部分针对实现接口中的方法定义具体的实现。要定义一个可供C++共享的Delphi对象,共享接口的说明应注意:
      在Delphi程序里,要共享的方法必须被说明为抽象(abstract),而且虚拟(virtual );
      在C++程序里,必须用关键字"virtual"及"=0"后缀,把从Delphi共享的方法说明成"pure virtual";
      共享的对象方法必须在两种语言里都被说明成相同的调用方式,通常使用标准系统调用方式(stdcall)。
      

  12.   

    下面,举例说明这些规则,假设有这样的一个Delphi对象:
    TTestObject=class
    procedure Proc1(x:integer);
    function Func1(x:integer):PChar;
    procedure Proc2;
    function Func2:integer;
    end;
      如果C++程序需要共享其中的方法Proc1、Func1,可把上述说明修改成以下形式:
    STestObject=class
    procedure Proc1(x:integer); virtual; abstract; stdcall;
    function Func1(x:integer); virtual; abstract; stdcall;
    end;
    TTestObject=class(STestObject)
    procedure Proc1(x:integer);
    fuction Func1(x:integer):PChar;
    procedure Proc2;
    fuction Func2:integer;
    end;在C++程序中做如下对象原型说明:
    class STestObject {
    virtual void Proc1(int x)=0;
    virtual char *Func1(int x)=0;
    };
      为了能在C++中成功地访问Delphi定义的类, Delphi接口说明时必须包含一个可共享的"制造函数(Factory Function)"CreateTestObject,该制造函数可被定义在动态链接库或目标文件(.OBJ)中,例如:
    Library TestLib;
    exports CreateTestObject;
    function CreateTestObject:STestObject; stdcall;
    begin
    Result:=TTestObject.Create;
    end;

    end.
      经过这样的处理,现在可在C++程序中使用这个由Delphi定义的对象,调用方式如下:
    extern "C" STestObject stdcall *CreateTestObject();
    void UseTestObject(void) {
    STestObject *theTestObject=CreateTestObject();
    theTestObject->Proc1(10);
    Char *str=theTestObject->Func1(0);
    }
      当调用制造函数CreateTestObject时,实际上已经在Delphi一侧占用了一个对象实例的空间,C++程序在针对该对象的所有处理完成后必须考虑释放这一空间,具体的实现可在Delphi中定义一个类,如上述Proc1的共享方法Free,以此来完成这一任务:
    STestObject=class
    procedure Proc1(x:integer); virtual; abstract; stdcall;
    function Func1(x:integer); virtual; abstract; stdcall;
    procedure Free; virtual; abstract; stdcall;
    end;

    implementation

    procedure TTestObject.Free;
    begin

    end;

    end.
    2.Delphi共享C++对象
      通常,程序员会考虑使用Delphi来编制用户界面,所以Delphi代码调用C++代码似乎显得更加实际些。其实,Delphi共享C++对象的实现方法与上述C++共享Delphi对象非常相似。用同样的共享接口与实现接口说明方法来定义C++的类:
    class STestObjedt {
    virtual void Proc1(int x)=0;
    virtual char *Func1(int x)=0;
    };
    class TTestObjedt :public STestObject {
    void Proc1(int x);
    char *Func1(int x);
    void Proc2();
    int Func2();
    void Free();
    };
      然后实现这些方法。同样地,C++对象需要一个与之对应的制造函数,这里以DLL为例
    STestObject stdcall export *CreateTestObject() {
    return (STestObject *) new TTestObject.Create;
    }
      Delphi代码可以通过调用制造函数CreateTestObject,很容易地在C++中创建实例,获得指向该实例的指针值,并以这个指针值来调用对象中的共享方法。当然,在进行完该对象的相关处理后,千万不要忘了调用Free释放占用的空间。 
    5555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555
    使用Dll:    unit MainFfm;interfaceuses
      SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
      Forms, Dialogs, StdCtrls;type
      { First, define a procedural data type, this should reflect the
        procedure that is exported from the DLL. }
      TShowCalendar = function (AHandle: THandle; ACaption: String): TDateTime; StdCall;  { Create a new exception class to reflect a failed DLL load }
      EDLLLoadError = class(Exception);  TMainForm = class(TForm)
        lblDate: TLabel;
        btnGetCalendar: TButton;
        procedure btnGetCalendarClick(Sender: TObject);
      end;var
      MainForm: TMainForm;implementation{$R *.DFM}procedure TMainForm.btnGetCalendarClick(Sender: TObject);
    var
      LibHandle   : THandle;
      ShowCalendar: TShowCalendar;
    begin  { Attempt to load the DLL }
      LibHandle := LoadLibrary('CALENDARLIB.DLL');
      try
        { If the load failed, LibHandle will be zero.
          If this occurs, raise an exception. }
        if LibHandle = 0 then
          raise EDLLLoadError.Create('Unable to Load DLL');
        { If the code makes it here, the DLL loaded successfully, now obtain
          the link to the DLL's exported function so that it can be called. }
        @ShowCalendar := GetProcAddress(LibHandle, 'ShowCalendar');
        { If the function is imported successfully, then set lblDate.Caption to reflect
          the returned date from the function. Otherwise, show the return raise
          an exception. }
        if not (@ShowCalendar = nil) then
          lblDate.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
        else
          RaiseLastWin32Error;                                                               
      finally
        FreeLibrary(LibHandle); // Unload the DLL.
      end;
    end;end.摘自Delphi5开发
    unit DLLFrm;interfaceuses
      SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
      Forms, Dialogs, Grids, Calendar;type  TDLLForm = class(TForm)
        calDllCalendar: TCalendar;
        procedure calDllCalendarDblClick(Sender: TObject);
      end;{ Declare the export function }
    function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime; StdCall;implementation
    {$R *.DFM}function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime;
    var
      DLLForm: TDllForm;
    begin
      // Copy application handle to DLL's TApplication object
      Application.Handle := AHandle;
      DLLForm := TDLLForm.Create(Application); 
      try
        DLLForm.Caption := ACaption;
        DLLForm.ShowModal;
        Result := DLLForm.calDLLCalendar.CalendarDate; // Pass the date back in Result
      finally
        DLLForm.Free;
      end;
    end;procedure TDLLForm.calDllCalendarDblClick(Sender: TObject);
    begin
      Close;
    end;end.
      

  13.   

    上边的宝贝是我在网上找到啊!
    在我看来,对我有很大的帮助的!
    我都把她打印下来!
    然好东西应该大家一起分享!我就把他贴出来,如果能给大家一点帮助的话,也算是我对CSDN的一点回报!
      

  14.   

    1:dll内容:
    library DllFormTest;uses
      SysUtils,
      Classes,
      Form1unt in 'Form1unt.pas' {Form1},
      Form2unt in 'Form2unt.pas' {Form2};{$R *.res}exports
      ShowForm ;begin
    end.2:
    unit Form1unt;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Form2unt, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;  function ShowForm :Boolean;implementation{$R *.dfm}function ShowForm :Boolean;
    var
      Form1: TForm1;
    begin
      Form1 :=TForm1.Create(Application);
      Form1.ShowModal ;
      try
        Form1.Caption :='我是DLL中的窗体!';
      finally
        Form1.Free ;
        result :=True;
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      Application.CreateForm(TForm2, Form2);
      Form2.ShowModal ;
    end;end.3:
    nit Form2unt;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ComCtrls;type
      TForm2 = class(TForm)
        TreeView1: TTreeView;
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form2: TForm2;implementation{$R *.dfm}end.
    4:主程序内容:
    unit TestDLL;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TShowForm = function :Boolean;  TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var
      LibHandle: THandle;
      ShowForm :TShowForm;
    begin
      LibHandle := LoadLibrary('DllFormTest.dll');
      try
        if LibHandle = 0 then
          raise Exception.Create('找不到DLL');
        @ShowForm := GetProcAddress(LibHandle, 'ShowForm');
        if @ShowForm = nil then
          raise Exception.Create('DLL文件中没有ShowForm函数')
        else
          ShowForm;
      finally
        FreeLibrary(LibHandle);
      end;
    end;end.
      

  15.   

    library XueyuanbiaoDll;{ 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,
      Departmentsunit in 'Departmentsunit.pas' {Xueyuanbianhao};{$R *.res}
    exports
    xueyuanbianhaoshow;
    //显示动态调用的窗体,xueyuanbiaohao!begin
    end.
      

  16.   

    dll中的其他部分!
    unit Departmentsunit;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, DB, ADODB, Grids, DBGrids, Buttons, ExtCtrls, StdCtrls, ComCtrls,
      Mask, DBCtrls;type
      TXueyuanbianhao = class(TForm)
        ADOConnection1: TADOConnection;
        ADOQuery1: TADOQuery;
        DataSource1: TDataSource;
        Panel1: TPanel;
        ScrollBox1: TScrollBox;
        SpeedButton1: TSpeedButton;
        SpeedButton2: TSpeedButton;
        SpeedButton3: TSpeedButton;
        SpeedButton4: TSpeedButton;
        DBGrid1: TDBGrid;
        Panel2: TPanel;
        SpeedButton5: TSpeedButton;
        Panel3: TPanel;
        Panel4: TPanel;
        RichEdit1: TRichEdit;
        DBEdit1: TDBEdit;
        DBEdit2: TDBEdit;
        Label1: TLabel;
        Label2: TLabel;
        BitBtn1: TBitBtn;
        BitBtn2: TBitBtn;
        Panel5: TPanel;
        Panel6: TPanel;
        Memo1: TMemo;
        Label3: TLabel;
        Label4: TLabel;
        BitBtn3: TBitBtn;
        DBEdit3: TDBEdit;
        DBEdit4: TDBEdit;
        GroupBox1: TGroupBox;
        DBNavigator1: TDBNavigator;
        procedure SpeedButton1Click(Sender: TObject);
        procedure SpeedButton4Click(Sender: TObject);
        procedure SpeedButton2Click(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
        procedure BitBtn2Click(Sender: TObject);
        procedure DBEdit1Change(Sender: TObject);
        procedure SpeedButton3Click(Sender: TObject);
        procedure BitBtn3Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
       procedure xueyuanbianhaoshow(pa1:Thandle;con1:Tadoconnection);cdecl;
    var
      Xueyuanbianhao: TXueyuanbianhao;implementation{$R *.dfm}
    procedure xueyuanbianhaoshow(pa1:Thandle;Con1:Tadoconnection);cdecl;
    var
            Xueyuanbianhao: TXueyuanbianhao;
    begin
            Application.Handle:=pa1;
            Xueyuanbianhao:=TXueyuanbianhao.Create(application);
            try
            xueyuanbianhao.ADOConnection1:=con1;
            xueyuanbianhao.ShowModal;
            finally
            Xueyuanbianhao.Free;
            end;
    end;
    //procedure TXueyuanbianhao.SpeedButton1Click(Sender: TObject);
    begin
            Panel1.Show;
            Panel2.Visible:=false;
            Panel5.Visible:=false;
            //显示浏览信息Panle!
    end;procedure TXueyuanbianhao.SpeedButton4Click(Sender: TObject);
    begin
            //Xueyuanbianhao;
            //关闭窗体!
    end;procedure TXueyuanbianhao.SpeedButton2Click(Sender: TObject);
    begin
            Panel2.Show;
            Panel1.Visible:=false;
            Panel5.Visible:=false;
            AdoQuery1.Append;
            //显示添加Panle1
    end;procedure TXueyuanbianhao.BitBtn1Click(Sender: TObject);
    begin
            AdoQuery1.Post;
            //添加数据!
            Bitbtn1.Visible:=false;
            Bitbtn2.Visible:=false;
            //防止按钮被按多次!
            Panel2.Visible:=false;
            Panel1.Show;
            //显示完了数据的时候,转移那个桌面!
    end;procedure TXueyuanbianhao.BitBtn2Click(Sender: TObject);
    begin
            AdoQuery1.Cancel;
            //取消添加数据!
            Bitbtn1.Visible:=false;
            Bitbtn2.Visible:=false;
            //防止按钮被按多次!
            Panel2.Visible:=false;
            Panel1.Show;
            //显示完了数据的时候,转移那个桌面!
    end;procedure TXueyuanbianhao.DBEdit1Change(Sender: TObject);
    begin
            Bitbtn1.Show;
            Bitbtn2.Show;
            //当数据发生改变的时候,显示按钮!
    end;procedure TXueyuanbianhao.SpeedButton3Click(Sender: TObject);
    begin
    Panel5.Show;
    Panel1.Visible:=false;
    Panel2.Visible:=false;
    //显示修改页面!
    end;procedure TXueyuanbianhao.BitBtn3Click(Sender: TObject);
    begin
            ADoquery1.Post;
            //提交数据!
            Panel1.Show;
            Panel2.Visible:=false;
            Panel5.Visible:=false;
            //显示浏览信息Panle!
    end;end.
      

  17.   

    工程:
    unit dlltestunit;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, ADODB;type
      TForm1 = class(TForm)
        Button1: TButton;
        ADOConnection1: TADOConnection;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
       procedure xueyuanbianhaoshow(pa1:thandle;Pa2:Tadoconnection);cdecl;
    external 'xueyuanbiaodll.dll';
    var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
    xueyuanbianhaoshow(Application.Handle,Form1.ADOConnection1);
    end;end.
      

  18.   

    有必要这样麻烦吗?
    在Dll中显示窗体只有一条路:动态创建窗体,且窗体的使用传进去的handle来创建,就ok了
      

  19.   

    //------------------来自delphi 5开发人员指南------------//
    {
    Copyright ?1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira
    }unit DLLFrm;interfaceuses
      SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
      Forms, Dialogs, Grids, Calendar;type  TDLLForm = class(TForm)
        calDllCalendar: TCalendar;
        procedure calDllCalendarDblClick(Sender: TObject);
      end;{ Declare the export function }
    function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime; StdCall;implementation
    {$R *.DFM}function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime;
    var
      DLLForm: TDllForm;
    begin
      // Copy application handle to DLL's TApplication object
      Application.Handle := AHandle;
      DLLForm := TDLLForm.Create(Application); 
      try
        DLLForm.Caption := ACaption;
        DLLForm.ShowModal;
        Result := DLLForm.calDLLCalendar.CalendarDate; // Pass the date back in Result
      finally
        DLLForm.Free;
      end;
    end;procedure TDLLForm.calDllCalendarDblClick(Sender: TObject);
    begin
      Close;
    end;end.
      

  20.   

    //-----------------来自delphi 5开发人员指南-------------//
    {
    Copyright ?1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira
    }unit MainFfm;interfaceuses
      SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
      Forms, Dialogs, StdCtrls;type
      { First, define a procedural data type, this should reflect the
        procedure that is exported from the DLL. }
      TShowCalendar = function (AHandle: THandle; ACaption: String): TDateTime; StdCall;  { Create a new exception class to reflect a failed DLL load }
      EDLLLoadError = class(Exception);  TMainForm = class(TForm)
        lblDate: TLabel;
        btnGetCalendar: TButton;
        procedure btnGetCalendarClick(Sender: TObject);
      end;var
      MainForm: TMainForm;implementation{$R *.DFM}procedure TMainForm.btnGetCalendarClick(Sender: TObject);
    var
      LibHandle   : THandle;
      ShowCalendar: TShowCalendar;
    begin  { Attempt to load the DLL }
      LibHandle := LoadLibrary('CALENDARLIB.DLL');
      try
        { If the load failed, LibHandle will be zero.
          If this occurs, raise an exception. }
        if LibHandle = 0 then
          raise EDLLLoadError.Create('Unable to Load DLL');
        { If the code makes it here, the DLL loaded successfully, now obtain
          the link to the DLL's exported function so that it can be called. }
        @ShowCalendar := GetProcAddress(LibHandle, 'ShowCalendar');
        { If the function is imported successfully, then set lblDate.Caption to reflect
          the returned date from the function. Otherwise, show the return raise
          an exception. }
        if not (@ShowCalendar = nil) then
          lblDate.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
        else
          RaiseLastWin32Error;                                                               
      finally
        FreeLibrary(LibHandle); // Unload the DLL.
      end;
    end;end.
      

  21.   

    在DLL中应该可以进行数据库方面的处理,与交互界面的处理吧?
      

  22.   

    老兄,我最近正好在研究这方面的技术。
    我看了你的代码,发现两个错误:
    1: 在需要导出的函数名称后要加stdcall关键字,否则调用很可能会有以外情况发生。2:  DLL中的窗体不能动态生成。也就是说,直接调用ght1.Show是不对的。我不知道你的ght  单元的代码是怎么写的,你可以这样参照一下:
        先在单元Unit1中把这句话:var ght: Tght去掉(如果有的话)
        在需要显示窗体的模块里写,ght := Tght.Create(Application),然后Show或这showModal均可。
        不要忘记在不需要的时候再释放掉它:ght.Free;
      

  23.   

    多谢了!!
    其实在delphi或者BCb中调用的,默认的调用方法效率可能是最高的!
    你是不是只看了第一部分啊!