求dll中对象操作异常解决办法 ( 积分: 200 )

  • 主题发起人 主题发起人 andrew57
  • 开始时间 开始时间
A

andrew57

Unregistered / Unconfirmed
GUEST, unregistred user!
有三个unit,其中一个声明引出类TManBLL接口UIbll.pas,其他两个声明类Udal和Ubll
第一个是Udal.pas实现数据库操作类
TManDAL = class
public
function fun1(parameter...):TDataSet;
end;
第二个UIbll.pas是提供TManDAL方法fun1的接口
IBLL = Interface
['{GUID}']
function fun1(parameter...):TDataSet;
end;
第三个是Ubll.pas业务逻辑类
TManBLL = class(TInterfaceObject,IBLL)
private
FManDAL: TManDAL;
function fun1(parameter...):TDataSet;
public
constructor create;
destructor Destory;
end;
//*******TManBLL********
constructor TManBLL.create;
begin
FManDAL := TManDAL.create; //这行注释问题消失
end;
Libaray 单元中:
function ManBLL: IBLL;stdcall;
begin
result := TManBLL.create;
end;
exports
ManBLL;
//************调用dll中函数***********
uses UIbll, Ubll;
function ManBLL: IBLL;stdcall; external 'dllName.dll';
procedure Btn1Click(Sender: TObject);
var
bll: IBLL;
qry: TADOQuery;
begin
bll := ManBLL; //执行到这里引发异常
qry := bll.fun1(....);
bll := nil;
end;
不知道为什么执行到dll中的FManDAL := TManDAL.create;就出异常,难道dll中不能初始化对象,但result := TManBLL.create;也对了!望高人赐教,急等待
 
constructor [red]TManBLL.create[/red];
begin
FManDAL := [blue]TManBLL.create;[/blue] //这行注释问题消失
end;

你觉得这样合适吗?构造函数引用自身?
 
我帖子上写错了,抱歉!应该是:
constructor TManBLL.create;
begin
FManDAL := TManDAL.create; //这行注释问题消失
end;
 
帮自己顶下
 
各位浏览后帮顶下
 
你不是要调用dll吗?
怎么不bll := ManBLL;
而是bll := TManBLL.create; //执行到这里引发异常

bll := ManBLL; 这样调用没异常啊

把你源码贴出来看看
 
帮你顶一个,接个分!
 
//********Udm***********
unit Udm;

interface

uses
SysUtils, Classes, DB, ADODB;

const
strConn = 'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;'+
'Initial Catalog=Test;Data Source=(local)';
type
TDM = class(TDataModule)
con1: TADOConnection;
ds1: TDataSource;
procedure DataModuleCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
DM: TDM;

implementation

{$R *.dfm}

procedure TDM.DataModuleCreate(Sender: TObject);
begin
DM.con1.ConnectionString := strConn;
DM.con1.LoginPrompt := False;
end;

end.
//***********Uentities*********
unit Uentities;
interface
type
TSex = class
private
FSex: string;
procedure SetSex(value: string);
function GetSex: string;
public
constructor create;
destructor Destory;
published
property Sex: string read GetSex write SetSex;
end;
/// <summary>
/// TMan's entity layer
/// </summary>
TMan = class
private
FName: string;
FSex: TSex;
procedure SetName(value: string);
function GetName: string;
procedure SexSex(value: TSex);
function GetSex: TSex;
public
constructor create;
destructor Destory;
published
property Name: string read GetName write SetName;
property Sex: TSex read GetSex write SexSex;
end;
implementation
{ TSex }
constructor TSex.create;
begin
FSex := '男'; //default
end;
destructor TSex.Destory;
begin
inherited;
end;
//********* ManDAL************
unit Udal;
interface
uses Uentities, Udm, ADODB, DB, Classes;
type
/// <summary>
/// TMan's data access layer
/// </summary>
TManDAL = class
private
adoQry: TADOQuery;
public
//Show
function Show(): TDataSet;
constructor Create;
destructor Destory;
end;
implementation
{ TManDAL }
constructor TManDAL.Create;
begin
inherited;
adoQry := TADOQuery.Create(Nil);
adoQry.Connection := DM.con1;
DM.ds1.DataSet := adoQry;
end;
destructor TManDAL.destory;
begin
if Assigned(adoQry) then
adoQry.Free;
inherited;
end;
/// <summary>
/// show all record
/// </summary>
function TManDAL.Show(): TDataSet;
begin
if Assigned(adoQry) then
begin
with adoQry do
begin
Close;
SQL.Clear;
SQL.Add('select * from man');
ExecSQL;
end;
end;
if not adoQry.IsEmpty then
Result := adoQry
else
Result := nil;
end;
end.
//**********IBLL*******
unit UIBLL;
interface
uses Uentities, DB;
type
IBLL = interface(IInterface)
['{BE0C11D9-BB6E-4943-B9BF-9669828D69F0}']
function Del(value: TMan): Boolean;
function Insert(value: TMan): Boolean;
function Show(): TDataSet;
end;
implementation
end.
//**********ManBLL************
unit UBLL;
interface
uses Udal, Uentities, UIBLL, DB, Classes;
type
/// <summary>
/// TMan's bussiness logic layer
/// </summary>
TManBLL = class(TInterfacedObject, IBLL)
private
FManDAL: TManDAL;
//show all record
function Show(): TDataSet;
public
constructor create;
destructor Destory;
end;
implementation
{ TManBLL }
constructor TManBLL.create;
begin
inherited;
FManDAL := TManDAL.Create; //这行使调用出错
end;
destructor TManBLL.Destory;
begin
if Assigned(FManDAL) then
FManDAL := nil;
inherited;
end;
function TManBLL.Show(): TDataSet;
begin
Result := FManDAL.Show();
end;
end.
//********Library Unit*********
library Layer;

{ 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,
ShareMem,
Uentities in 'Uentities.pas',
Udm in 'Udm.pas',
UBLL in 'UBLL.pas',
UIBLL in 'UIBLL.pas';

{$R *.res}

function ManBLL: IBLL; stdcall;
begin
Result := TManBLL.create;
end;

exports
ManBLL;

begin
end.
//**********实现调用dll*****
unit Umain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, DBGrids, ADODB, StdCtrls, DB, UIBLL;

type
TForm1 = class(TForm)
dbgrd1: TDBGrid;
btn1: TButton;
btnAdd: TButton;
btnDel: TButton;
edtName: TEdit;
lbl1: TLabel;
lbl2: TLabel;
cbbSex: TComboBox;
ds1: TDataSource;
procedure dbgrd1CellClick(Column: TColumn);
procedure btnAddClick(Sender: TObject);
procedure btnDelClick(Sender: TObject);
procedure dbgrd1DblClick(Sender: TObject);
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
function ManBLL: IBLL; stdcall; external 'Layer.dll';

implementation

uses Uentities;

{$R *.dfm}


procedure TForm1.btn1Click(Sender: TObject);
var
showMan: IBLL;
begin
showMan := ManBLL;
ds1.DataSet := showMan.Show;
showMan := nil;
end;
end.
代码已经全部贴出,望各位帮找下错误
 
好好学学面向对象的基本知识,有你这么创建对象的吗????

随便打开一个Delphi提供的源代码看看是怎么创建的
 
能具体点说明是那个地方错误吗?
不要只留下模糊的文字!
我看刘艺写的《delphi面向对象的编程思想》也是这么写的啊,通过接口引用方法。
望指教。
 
好家伙,你写的东西还真绕呢,TManBLL是实现接口的是吧,TManDAL又有什么用?完全可以把TManDAL要实现的东西在TManBLL里面完成吧

adoQry := TADOQuery.Create(Nil);
adoQry.Connection := DM.con1;
[red]DM.ds1.DataSet := adoQry;[/red] 这一句有什么用?
 
DataModual单元没贴出,那是从DataModual中引用的Adoconnection 和Adoquery
我是想把对数据库的操作和方法的调用分开
想法是把对数据库的操作和表示层分离,所以我就想封装到dll里面
,这里只是测试下查询能不能实现
 
基础太差还是太马虎了?不觉得下面的代码在dll中有问题吗?

unit Udal;
...
constructor TManDAL.Create;
begin
inherited;
adoQry := TADOQuery.Create(nil);
adoQry.Connection := DM.con1;
DM.ds1.DataSet := adoQry;
end;
 
代码有问题?
那时另一个文件里的对象,我有一个单元没有给出,现在在原基础上给出
代码没有语法问题,能正确生成dll文件,但程序中调用会出现EAccessViolation异常
不封装进dll给出的代码可以正确运行
还望具体说明。
 
还看不出来?调试报错也看不出个所以然?这个问题和dm单元的代码没关系,就你现在贴出的代码,dll中根本就没有DM实例,怎么会不出错?!!!
 
var
DM: TDM;
怎么没有,说了没有贴出datamodule单元代码
这个单元是程序运行时在program单元自动加载的
我想已经实例了
 
应该是没有实例化,这里不会自动实例
 
接受dirk的答案,是没有实例化dm,一直没想到这是dll(必须手动生成实例),而不是exe里面,谢谢各位的帮忙,问题不大,没找准,折腾了一天
 
dm只是你的一个单元,TManDAL.Create在引用这个单元的内容的时候,首先要确定这个单元已经创建
 
后退
顶部