DLL中传递结构指针的问题

赖皮鹏 2008-10-23 10:57:41
dll中函数:
procedure getCardInfo(var aList:pInfo;iPort:integer=0);stdcall;
var
p : pInfo;
begin
getMem(p,sizeof(TInfo));
p^.Succmk := 1;
p^.aMess := 'ee';
p^.aNum := '2003';
p^.CardNo := 'AF53D7E2';
p^.aName := 'Test';
p^.aMoneyje := 24;
p^.aLimitM := 30;

aList := p;
freemem(p);
end;

结构体声明:
pInfo = ^TInfo;
//反馈信息
TInfo = record
Succmk : Integer; //成功标志 0 成功 1 失败
aMess: pchar; //失败原因
aNum : pchar; //编号
CardNo : pchar; //卡号
aName : pchar; //姓名
aMoneyje : Double; //当前卡余额
aLimitM : Double; //交易上限额度
end;

主程序调用:
procedure getCardInfo(var stuList:pStuInfo;iPort:integer=0);external 'PaySelf.dll';

procedure TForm1.Button1Click(Sender: TObject);
var
tt : pInfo;
begin
try
getMem(tt,Sizeof(TInfo));
getCardInfo(@tt);
getCardInfo(tt);
//test(tt);
Memo1.Lines.Add(tt.aNum);
Memo1.Lines.Add(tt.CardNo);
FreeMem(tt);
except
on e:exception do
showmessage(e.Message);
end;
end;

想实现的功能是传入一个空结构体,由DLL处理后返回
现在的问题是在DLL中读取传入指针被改变后的值都是对的,但是在主程序中无法获得改变的值。
并且在未添加try语句时会报内存错误

哪位高手能为我答疑?
...全文
223 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
ZyxIp 2008-10-23
  • 打赏
  • 举报
回复
原则就是你给DLL传递进去的是一个分配好内存的指针,DLL只管填写内容不能进行显式或隐式的内存分配.
ZyxIp 2008-10-23
  • 打赏
  • 举报
回复
在DLL中调用 getMem(p,sizeof(TInfo)); 要在DLL中FREE才行.

TInfo = record
Succmk : Integer; //成功标志 0 成功 1 失败
aMess: Variant; //失败原因
aNum : Variant; //编号
CardNo : Variant; //卡号
aName : Variant; //姓名
aMoneyje : Double; //当前卡余额
aLimitM : Double; //交易上限额度
end;

TInfo = record
Succmk : Integer; //成功标志 0 成功 1 失败
aMess: Array[0..256] of char; //失败原因
aNum : Array[0..64] of char;; //编号
CardNo : Array[0..64] of char;; //卡号
aName : Array[0..64] of char;; //姓名
aMoneyje : Double; //当前卡余额
aLimitM : Double; //交易上限额度
end;

原则就是你给DLL传递进去的是一个分配是内存的指针,DLL只管填写内容不可能进行显式或隐式的分配内存.
赖皮鹏 2008-10-23
  • 打赏
  • 举报
回复
回3楼,那用什么类型呢?char?
赖皮鹏 2008-10-23
  • 打赏
  • 举报
回复
不行吧?

不分配内存?不赋值?
xutaiqing 2008-10-23
  • 打赏
  • 举报
回复
  pInfo = ^TInfo; 
//反馈信息
TInfo = record
Succmk : Integer; //成功标志 0 成功 1 失败
aMess: pchar; //失败原因
aNum : pchar; //编号
CardNo : pchar; //卡号
aName : pchar; //姓名
aMoneyje : Double; //当前卡余额
aLimitM : Double; //交易上限额度
end;

首先从这个结构上来看,就存在着极大的内存管理漏洞,pchar是一个字符指针,本身并不能完成内存的管理,如果用作返回信息,那么相应的内存又由谁来分配?谁来释放?
lake_cx 2008-10-23
  • 打赏
  • 举报
回复
上面的有地方错了,在Delphi中一般这么写:
一般这样用
dll中函数:
procedure getCardInfo(var aList:TInfo;iPort:integer=0);stdcall;
begin
aList.Succmk := 1;
aList.aMess := 'ee';
aList.aNum := '2003';
aList.CardNo := 'AF53D7E2';
aList.aName := 'Test';
aList.aMoneyje := 24;
aList.aLimitM := 30;
end;

主程序调用:
procedure getCardInfo(var aList:TInfo;iPort:integer=0);external 'PaySelf.dll';

procedure TForm1.Button1Click(Sender: TObject);
var
tt : TInfo;
begin
try
getCardInfo(tt);
Memo1.Lines.Add(tt.aNum);
Memo1.Lines.Add(tt.CardNo);
except
on e:exception do
showmessage(e.Message);
end;
end;
lake_cx 2008-10-23
  • 打赏
  • 举报
回复
一般这样用
dll中函数:
procedure getCardInfo(aList:pInfo;iPort:integer=0);stdcall;
var
p : pInfo;
begin
p^.Succmk := 1;
p^.aMess := 'ee';
p^.aNum := '2003';
p^.CardNo := 'AF53D7E2';
p^.aName := 'Test';
p^.aMoneyje := 24;
p^.aLimitM := 30;
end;

主程序调用:
procedure getCardInfo(stuList:pStuInfo;iPort:integer=0);external 'PaySelf.dll';

procedure TForm1.Button1Click(Sender: TObject);
var
tt : TInfo;
begin
try
getCardInfo(@tt);
Memo1.Lines.Add(tt.aNum);
Memo1.Lines.Add(tt.CardNo);
except
on e:exception do
showmessage(e.Message);
end;
end;
赖皮鹏 2008-10-23
  • 打赏
  • 举报
回复
哦,明白了。结贴!
liangpei2008 2008-10-23
  • 打赏
  • 举报
回复
你在主程序中getMem(tt,Sizeof(TInfo))为TInfo分配了内存,并通过地址传递至DLL中,为何在DLL中还要进行分配内存?
在DLL中又分配了一次内容,其地址已经不是在主调函数中传递的TInfo的地址了,所以主程序中无法获得改变的值!

lake_cx 的做法是对的!

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧