关于DLL的应用问题 ( 积分: 50 )

  • 主题发起人 主题发起人 gdzscj
  • 开始时间 开始时间
G

gdzscj

Unregistered / Unconfirmed
GUEST, unregistred user!
我写了一个DLL程序发下,但在运行时出现内存错误的情况,请大家给我看看是什么问题?
library maildll;


uses
SysUtils,
Classes,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
exports
codetogid;
begin
end.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB;

type
TForm1 = class(TForm)
ADOQuery1: TADOQuery;
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
function codetogid(objects:string;code:string):integer;stdcall;

implementation

{$R *.dfm}
function codetogid(objects:string;code:string):integer;stdcall;
begin
form1.adoquery1.Close;
form1.adoquery1.SQL.Text:='select gid from '+objects+' where code='''+code+'''';
form1.adoquery1.Open;
if form1.adoquery1.RecordCount>0 then result:=form1.adoquery1.fieldbyname('gid').AsInteger else result:=0;
end;

end.

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, 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 codetogid(objects:string;code:string):integer;stdcall;external 'maildll.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
edit1.Text:=inttostr(codetogid('goods','03020060'));
end;

end.
 
我写了一个DLL程序发下,但在运行时出现内存错误的情况,请大家给我看看是什么问题?
library maildll;


uses
SysUtils,
Classes,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
exports
codetogid;
begin
end.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB;

type
TForm1 = class(TForm)
ADOQuery1: TADOQuery;
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
function codetogid(objects:string;code:string):integer;stdcall;

implementation

{$R *.dfm}
function codetogid(objects:string;code:string):integer;stdcall;
begin
form1.adoquery1.Close;
form1.adoquery1.SQL.Text:='select gid from '+objects+' where code='''+code+'''';
form1.adoquery1.Open;
if form1.adoquery1.RecordCount>0 then result:=form1.adoquery1.fieldbyname('gid').AsInteger else result:=0;
end;

end.

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, 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 codetogid(objects:string;code:string):integer;stdcall;external 'maildll.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
edit1.Text:=inttostr(codetogid('goods','03020060'));
end;

end.
 
1、从DLL中导出的函数最好用PCHAR型的字符串进行传递。
2、你的DLL好像没有必要先建个表单,直接用数据库对象操作应该就可以的了。
 
楼上说得对,补充一下,如果一定要使用string
看看你的工程文件的这段注释:
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. }

 
请问,你的form1是什么地方创建的?
 
ADOQuery1只定义了,但是没有创建,怎么会不出错呢?
 
dll中的form要自己创建:
function codetogid(objects:string;code:string):integer;stdcall;
begin
form1:=tform1.create(nil)
//add
try
form1.adoquery1.Close;
form1.adoquery1.SQL.Text:='select gid from '+objects+' where code='''+code+'''';
form1.adoquery1.Open;
if form1.adoquery1.RecordCount>0 then result:=form1.adoquery1.fieldbyname('gid').AsInteger else result:=0;
finally
freeandnil(form1)
///add
end;
end;
 
补充一下
如果你一定要用string的话,还可以用shortstring或widestring来代替
 
我估计是你dll里面的form1名字和你调用工程里面的form1名字重复。
 
分别在你Dll中加入sharemem,和在exe加入sharemem单元.
 

function codetogid(objects:string;code:string):integer;stdcall;
最好不要用String,用PChar

动态连接库的创建
File->New->Other->New选项页->DLL Wizard
 
把上面的
function codetogid(objects:string;code:string):integer;stdcall;
begin
form1.adoquery1.Close;
form1.adoquery1.SQL.Text:='select gid from '+objects+' where code='''+code+'''';
form1.adoquery1.Open;
if form1.adoquery1.RecordCount>0 then result:=form1.adoquery1.fieldbyname('gid').AsInteger else result:=0;
end;

裡面的FORM1,都改成self,試試吧

 
谢谢各位的意见。
我把dll中的form1 改为dllform,也把string改为shotstring,但错误依旧。
我按TYZhang的意见加入“dllform:=Tdllform.create(nil),出现错误:未调用CoInitialize。
 
to gdzscj:
这是因为你的form上有ado控件,即com组件,所以要初始化com环境,这样改:
function codetogid(objects:string;code:string):integer;stdcall;
begin
CoInitialize(nil);//new add
form1:=tform1.create(nil)
//add
try
form1.adoquery1.Close;
form1.adoquery1.SQL.Text:='select gid from '+objects+' where code='''+code+'''';
form1.adoquery1.Open;
if form1.adoquery1.RecordCount>0 then result:=form1.adoquery1.fieldbyname('gid').AsInteger else result:=0;
finally
freeandnil(form1)
///add
CoUninitialize;//new add
end;
end;
 
同意楼上的观点
to: yf_zq
我想问你sharemem这是个什么单元,
有什么意思吗?
 
在 use 部分 加 activex 单元

在Unit1 中的最后段加
initialization
CoInitialize(nil);
 
首先一个明显错误就是没在uses第一行加上sharemem.
 
我把程序改为:
function codetogid(objects:shortstring;code:shortstring):integer;stdcall;
begin
CoInitialize(nil);
dllform:=tdllform.create(nil);
try
dllform.adoquery1.Close;
dllform.adoquery1.SQL.Text:='select gid from '+objects+' where code='''+code+'''';
dllform.adoquery1.Open;
if dllform.adoquery1.RecordCount>0 then result:=dllform.adoquery1.fieldbyname('gid').AsInteger else result:=0;
finally
freeandnil(dllform);
end

CoUninitialize;
end;

运行通过,但在退出时又出错:invalid pointer operation。
这是为什么呢?
 
哪位大大能解决这最后的错误?
 
function codetogid(objects:shortstring;code:shortstring):integer;stdcall;
改为
function codetogid(App : TApplication;objects:shortstring;code:shortstring):integer;stdcall;
创建时候使用,
function codetogid(App : TApplication
objects:shortstring;code:shortstring):integer;stdcall;
begin
// CoInitialize(nil)

Application := App;
dllform:=tdllform.create(App);
try
dllform.adoquery1.Close;
dllform.adoquery1.SQL.Text:='select gid from '+objects+' where code='''+code+'''';
dllform.adoquery1.Open;
if dllform.adoquery1.RecordCount>0 then result:=dllform.adoquery1.fieldbyname('gid').AsInteger else result:=0;
finally
freeandnil(dllform);
end

// CoUninitialize;
end;

更好的设计,把ADO也动态创建,用完后释放。
 

Similar threads

I
回复
0
查看
673
import
I
I
回复
0
查看
686
import
I
I
回复
0
查看
778
import
I
I
回复
0
查看
709
import
I
S
回复
0
查看
830
SUNSTONE的Delphi笔记
S
后退
顶部