而且调用时产生内存读错误码的对话框。下面是DLL源码:
这里面的函数是进行英文的中文译的,从数据库中找中文。关键是ADOConnection1和ADOQuery1的动态生成问题,好象把握得不好,将这个函数放到DELPHI的本地窗体中使用是对的,放在DLL函数中引用就出错,请高手帮助一下呀!!!
library engtochs;{ 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
  Messages,
  Variants,
  Graphics,
  Controls, 
  StdCtrls,
  SysUtils,
  Windows,
  DB,
  ADODB,
  Classes;
{$R *.res}
var
 ADOConnection1:TADOConnection;
 ADOquery1:TADOQuery;function GetModulePath:string;
var
  Buffer : array[0..260] of char;
  temp: string;
begin
  SetString(temp, Buffer, GetModuleFileName(Hinstance, Buffer, SizeOf(Buffer)));
  Result := ExtractFilePath(temp);
end;function englishtochinese(english:pchar):pchar;export;stdcall;
var
 s:string;
beginif not fileexists(GetModulePath+'DLMGR.mdb') then  
  begin
    s:='找不到英语词库文件dlmgr.mdb';
    englishtochinese:=pchar(s);
    exit;
  end
  else
  begin
      ADOConnection1.Create(ADOConnection1);   //这括号里改为self不行。
      ADOquery1.Create(ADOquery1);              //这括号里改为self不行。
      s:='Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+GetModulePath+'DLMGR.mdb;Mode=Share Deny None;Extended Properties="";Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;';
      ADOConnection1.ConnectionString:=s;
      ADOQuery1.Connection:=ADOConnection1;
      ADOConnection1.open;
      ADOQuery1.SQL.Clear;
      ADOQuery1.SQL.Add('select * from 英语字典 where word="'+trim(english)+'"');
      ADOQuery1.Open;
        if ADOQuery1.RecordCount<1 then
          begin
            s:='找不到这个单词,请检查拼写';
            englishtochinese:=pchar(s);
          end
          else
            begin
              while not ADOQuery1.eof do
              begin
              s:=ADOQuery1.fieldbyname('word').AsString;
              s:=s+#13+#10+'['+ADOQuery1.fieldbyname('pronunce').AsString+']';
              s:=s+#13+#10+ADOQuery1.fieldbyname('mean').AsString;
              s:=s+#13+#10+ADOQuery1.fieldbyname('explain').AsString;
              s:=s+#13+#10+ADOQuery1.fieldbyname('example').AsString;
              s:=s+#13+#10;
              ADOQuery1.Next;
              end;
              englishtochinese:=pchar(s);
            end;
  end;end;
exports
  englishtochinese;
begin
end.

解决方案 »

  1.   

    因为Ado组件是ActiveX,所以,在dll中用到时,要初始化,先用如下语句:
    CoInitialize(nil);
    最后,在程序退出前,用: CoUninitialize;
    记得要uses ActiveX;
    还有,我习惯用 Create(nil); 或 Create(self); 
    我在我以前的一个项目中,在dll使用ado相关的组件,没什么问题,如你还有问题,可提出来!你的问题不用提两次啊,还有,用 XXXX.Create(nil); 一般没问题,但要记住,最后自己在最后释放该资源!
      

  2.   

    非常感谢!!!
    我也查了一下,找到了一些答案。
    按您说的做了,正确。但是还有一点小问题。就是什么是“程序退出之前”?是不是就是DLL中的函数的结尾处?因为我这是Liberay,不是Application.  目前我的程序在调用多次后,内存占用就大了。另外,为什么在DLL动态库的代码编中不能使用 self? 少引用了什么单元?form 等单元引入了还是不能用:
    adoquery1.create(self); 是错的。关键词self不认识。
      

  3.   

    Self关键字只在声明的Class中有效,你的function englishtochinese(english:pchar):pchar;export;stdcall;属于什么Class啊???
      

  4.   

    >>就是什么是“程序退出之前”?是不是就是DLL中的函数的结尾处?因为我这是Liberay,不是Application.  目前我的程序在调用多次后,内存占用就大了。这要看你是静态调用你的dll,还是动态,如果是静态,那你虽然调用完该dll的函数,该dll还是留在内存,如果你是动态的,那也要到你调用 FreeLibrary,该dll才从内存清除!理论上,一次初始化,一次清理就够了.
    但具体到你的代码,那就要是在函数的开始与最后加上这些代码,不过,看你的函数,如果多次调用,效率比较差,因为,要多次Create数据连接!!!Self一般指所应用的类自身!象你的函数中,那个self应该是指向Application!!!
      

  5.   


          ADOConnection1.Create(ADOConnection1);  
    天啊,这怎么能运行
     ADOConnection1 := TADOConnection.Create(nil)
      

  6.   

    ADOConnection1.Create(ADOConnection1);   //这括号里改为self不行。
          ADOquery1.Create(ADOquery1);              //
    ========
    错.....................
      

  7.   

    TO  aiirii(aiirii) 老师:
    您指导得太对了!!!我现在正在为速度快发愁呢。 我的同事说这个查询需要300ms , 不合格,请教您,您一定会有办法帮我提高速度的,能不能给明示一下,如何做成一次初始化,一次清理?动态和静态在代码编写上哪里有区别?我怎么才能一次Create数据连接而不是多次? 非常得感谢您!
      

  8.   

    self  是指引用当前对象,这要在类的方法里才能使用。
    想一次create数据连接而不是多次,你要把Adoconnecion连接的建立放在另一个过程或函数里,程序运行时就先调用建立Adoconnection的函数并保存在对象里,查询时传递Adoconnection连接对象即可。程序退出时再销毁Adoconnection连接对象。其实这个连接对象可以在程序里直接建立跟不调用DLL时一样,调用Dll里的查询函数时把
    对象传入查询函数即可,这样比较方便。
      

  9.   

    谢谢楼上的!
    请教:
    1. 我写的是让VC++调用的DLL模块,能在VC++中建立数据库连接再传给DLL中的函数吗?
    2. 如果全部写到我的DLL中,分两个函数让C调用,那么这两个函数间如何考虑生存期?即怎么实现打开数据库后不关上,让64个以上的用户不断使用DLL中查询函数时,保证数据库只打开一次再不关上(直到VC++程序关闭时,再通过函数调用来显式地关闭)? 非常感谢能够指教!!!
      

  10.   

    你将ADOConnection,ADOXXX都声明为全局变量,然后,再分别用两个函数来初始化创建与退出清理相关的资源就可啊!
    然后,在你现在提供的函数中只提供查询功能就可!
    如果你不想另外一个程序,如VC调用,还要麻烦来调用初始化与退出的函数,你可考虑将你的代码单独写在一个Unit中,然后再在unit中利用
    initialization  finalization
    来达到初始化与退出前的处理!我建议不要传递数据库连接给DLL,那样处理比较麻烦,出错的可能比较大!另外,就是,如果你是用LoadLibrary 来装载dll,那就是动态连接了,函数中的东西,当然在运行完函数就没了,所以,你要声明成全局变量!