关于Dll和数据库的疑问,请高手指点一下。(100分)

  • 主题发起人 主题发起人 dirk
  • 开始时间 开始时间
D

dirk

Unregistered / Unconfirmed
GUEST, unregistred user!
我刚开始做Dll程序,其中用到ADO,开始总出错,说是没有调用CoInitialize,
由于公司里上班时间不能上网,只好狂找帮助,总算解决,uses ComObj,调用
CoInitializeEx(nil,0),一切ok,但是又产生几个问题:uses ActiveX,调用
Initialize(nil),也一样可以连数据库,似乎没有什么问题,那么两者的区别
是什么?其中ComObj单元也use了ActiveX,看CoInitializeEx的定义(见下),
type
TCoInitializeExProc = function (pvReserved: Pointer;
coInit: Longint): HResult
stdcall;
{$EXTERNALSYM TCoInitializeExProc}
var
CoInitializeEx: TCoInitializeExProc = nil;
{$EXTERNALSYM CoInitializeEx}
这个函数应该是外部引用进来的函数,是否就是ActiveX单元的

function CoInitializeEx(pvReserved: Pointer
coInit: Longint): HResult
stdcall;
……
function CoInitialize
external ole32 name 'CoInitialize';
function CoInitializeEx
external ole32 name 'CoInitializeEx';

函数?

看了一会儿帮助,发现总是提到一个函数OleInitialize,The OleInitialize function
initializes the OLE library. You must initialize the library before you can
call OLE functions.

Unit ActiveX;
……
function OleInitialize
external ole32 name 'OleInitialize';
procedure OleUninitialize
external ole32 name 'OleUninitialize';

我又试了一下,发现uses ActiveX,只用OleInitialize(nil),一样也能连接数据库,我
很疑惑,CoInitialize,CoInitializeEx,OleInitialize,使用任何一个后,都可以在Dll
中连接数据库,它们之间难道没有什么区别吗?起码CoInitializeEx比其他个多个不明白
是干吗的LongInt参数,我想它们之间应该是有区别的吧?

还有,我是否一定要用OleUninitialize或CoUninitialize函数去释放内存?用完就释放应该
是好习惯,但我在程序中总是要用到这些Dll函数产生Form去操作数据库,每次都
initialize,Uninitialize,是不是太麻烦了,也影响效率,Exe程序退出时,系统是否会自
动做Uninitialize的工作去释放内存?

请高手们指点一下。

谢谢。
 
CoInitialize(nil)的意思好像就是初始化一个com对象!
 
DLL中用到ADO没所谓啊,不用搞什么CoInitialize,
不过你不要传递对象参数。只传递连接参数就行了。
这样,你的DLL还可以在别的语言中使用。当然,要PCHAR,不要STRING。
 
to kkyy:
要CoInitialize的,因为我的dll包含了完整的数据处理窗体,要创建TADOConnection
对象,不用CoInitialize肯定出错。

我希望有人为我解释一下CoInitialize,CoInitializeEx,OleInitialize的区别,我不希
望在发布程序后才发现有问题。

另外,我上面的第二个问题,关于CoUninitialize的问题:

>是否一定要用OleUninitialize或CoUninitialize函数去释放内存?用完就释放应该是好习
>惯,但我在程序中总是要用到这些Dll函数产生Form去操作数据库,每次都initialize,
>Uninitialize,是不是太麻烦了,也影响效率,Exe程序退出时,系统是否会自动做
>Uninitialize的工作去释放内存?

在 CoInitialize的帮助中说:
must be balanced by a corresponding call to the CoUninitialize function.
我想在dll初始化和释放时做CoInitialize和CoUninitialize工作,我本想这样解决:
begin
initialization // <- 出错
CoInitialize(nil);

finalization
CoUninitialize;
end.

总是提示“Statement expected but 'INITIALIZATION' found”错误,看了帮助才知道,
initialization、finalization是只能出现在Unit中的。

dll的

begin
……
end.

部分是dll的初始化部分吧,那么释放的部分呢?我看了帮助,有这样的一段:
var
SaveExit: Pointer;
procedure LibExit;
begin
CoUninitialize
// library exit code
ExitProc := SaveExit
// restore exit procedure chain
end;

begin
SaveExit := ExitProc
// save exit procedure chain
ExitProc := @LibExit
// install LibExit exit procedure
end.

就帮助上说的,应该是dll的释放部分:

When a DLL is unloaded, the library's exit procedures are executed by repeated calls to the address stored in ExitProc, until ExitProc becomes nil. The initialization parts of all units used by a library are executed before the library's initialization code, and the finalization parts of those units are executed after the library's exit procedure.

但就我跟踪看来,这个LibExit根本就没有执行,那么ExitProc到底该怎么用呢?

 
initialization
Coinitialize(nil);
finalization
CoUninitialize;


呵呵

行不行??
 
在dll中你试过就知道,不行!

我上面不是说了吗?

总是提示“Statement expected but 'INITIALIZATION' found”错误,看了帮助才知道,
initialization、finalization是只能出现在Unit中的。

你到delphi的帮助里去查“initialization (libraries),”,再查“finalization section,”,
显示的帮助是:
The finalization section is optional and can appear only in units that have an initialization section.
~~~~~~~~~~~~~~~~~~~~~~~~
可见只能用在Unit里的,而且我试过把
initialization
Coinitialize(nil);
finalization
CoUninitialize;
放到dll的其他部分,都出错!
 
你把它放在Unit不行吗?
我记得去年我这么用过~
 
to Nizvoo:
不明白你的意思,我是要对dll进行初始化和释放,放在Unit中算什么意思?
你写个dll,再跟踪执行一下,就会发现,dll的初始化是在调用程序的
Application.Initialize 之前进行的,在调用程序结束时释放的,我用F7跟踪后发现
在调用过程结束时,那个绿色的运行箭头也指向 dll 的Begin部分???
好奇怪!
其实我是看了CoInitialize的帮助:
must be balanced by a corresponding call to the CoUninitialize function.
想在dll初始化和释放时做CoInitialize和CoUninitialize工作,但现在不知道要怎么办了!
 
我试试再和你讨论,呵呵。
可能我的话有点武断,

先试试~

 
唉,还是不明白,我说不用Coinitialize可以,当然是这样用过的了,
我的通用权限管理模块,通用报表模块,等等,都没用Coinitialize,还卖钱了,要是不能用,别人不骂我呀。
 
我正是出错了才狂找帮助的啊!老大!

如果没有CoInitialize,系统的出错提示:
Project Project1.exe raised exception class EOleSysError with message '尚未调用 CoInitialize。'.Process stopped.Use Stop or Run to continue.

以下是Dll Project,包含一个Unit3
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,
Controls,
Forms,
Dialogs,
StdCtrls,
windows,
Classes,
ActiveX,
// ShareMem,
// ComObj,
Unit3 in 'Unit3.pas' {Form3};

type

{$R *.RES}

procedure openaform();stdcall;
begin
Form3:= TForm3.Create(nil);
Form3.Show ;
end;


exports
openaform;

begin
// CoInitialize(nil)
//没有这句话,openaform执行不出错?真不懂,你试试看嘛!
end.

////////////////////////////////////////////////////
//以下是Unit3

unit Unit3;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Db, ADODB, Grids, DBGrids, ComCtrls;

type
TForm3 = class(TForm)
Button1: TButton;
ADOC: TADOConnection;
ADOQ1: TADOQuery;
ADODataSet1: TADODataSet;
DBGrid1: TDBGrid;
DataSource1: TDataSource;
TreeView1: TTreeView;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form3: TForm3;

implementation

{$R *.DFM}

procedure TForm3.Button1Click(Sender: TObject);
begin
ADOC.LoginPrompt :=false;
ADOC.ConnectionString :='DRIVER={SQL Server};server=10.10.10.124;database=mydb;uid=sa;pwd=';
ADOC.Open ;
ADOQ1.Open ;

end;

end.


///////////////////////////////////////////
//以下是我的主程序

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls;

type
TForm1 = class(TForm)
Button8: TButton;
procedure Button8Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}
procedure openaform;stdcall;External'project2.dll';

procedure TForm1.Button8Click(Sender: TObject);
begin
openaform;
end;

end.
 
同我联系:qq:33771608
 
dll中的form1 没有释放,会不会有内存泄漏
 
你跟踪不到Dllproc是因为你使用的Delphi6
 
oh,刚才有人来拜访,现在才又上来,sorry,我不用QQ。
form在close事件中释放,应该没问题,我用的是Delphi5。
 
释放动态连接库试试
 
你说的是 FreeLibrary ?这个好像是对用 loadlobrary 装载的dll才要用的吧?

还有,我的问题是:

>我希望有人为我解释一下CoInitialize,CoInitializeEx,OleInitialize的区别。



>是否一定要用OleUninitialize或CoUninitialize函数去释放内存?用完就释放应该是好习
>惯,但我在程序中总是要用到这些Dll函数产生Form去操作数据库,每次都initialize,
>Uninitialize,是不是太麻烦了,也影响效率,Exe程序退出时,系统是否会自动做
>Uninitialize的工作去释放内存?
 
Delphi 5开发人员指南不是有设置dll出入口函数的例子么,
在dll的.dpr文件添加如下的代码:
procedure DLLEntryPoint(dwReason: DWord);
begin
case dwReason of
DLL_PROCESS_ATTACH: CoInitialize(nil);
DLL_PROCESS_DETACH: CoUninitialize;
end;

begin
{ First, assign the procedure to the DLLProc variable }
DllProc := @DLLEntryPoint;
{ Now invoke the procedure to reflect that the DLL is attaching
to the process }
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.

但是这3个函数之间的区别,还有待高手指点。[:)]
另外,你的form3用的show显示,但没有进行引用计数,也没有释放资源,
会发生内存泄漏吧。
 

Similar threads

S
回复
0
查看
738
SUNSTONE的Delphi笔记
S
S
回复
0
查看
730
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部