labview 读取zigbee数据采集模块的数据,打包成dll我用delphi调用,报内存冲突。access violation at 0x300053e0:read of address 0x00000000'
但是用VC调用同样的DLL却没有问题。请问是为什么?
程序如下:(动态调用dll)
privatepublicend;
type td1=record
elt1:double;
elt2:double;
elt3:double;
elt4:double;
end;
PTD1=TD1;
Tzigbee1=procedure(zigbee:PTD1);stdcall;implementation
procedure DAQ1;external 'SharedLib.dll';procedure Tform1.button1click(sender:tobject);
var midWare:TD1;
dllhandle:thandle;
pro:Tzigbee1;
begin
dllhandle:LoadLibrary('SharedLib.dll');
try
@pro:=getprocAddress(DllHandle,'zigbee1');
if assigned(@pro) then
begin
pro(midWare);
memo1.lines.add(floattostr(midware.elt1))
end;
finally
freeLibrary(dllhandle);
end;
end;
我单步调试,程序运行到最后一句都没有错,再执行 就报刚刚的内存突冲。哪位高手给解答一下嘛,急死了。
我把我所有的分都拿出来了,如果解决了,我去挣分再给您补多一些。不胜感激;
但是用VC调用同样的DLL却没有问题。请问是为什么?
程序如下:(动态调用dll)
privatepublicend;
type td1=record
elt1:double;
elt2:double;
elt3:double;
elt4:double;
end;
PTD1=TD1;
Tzigbee1=procedure(zigbee:PTD1);stdcall;implementation
procedure DAQ1;external 'SharedLib.dll';procedure Tform1.button1click(sender:tobject);
var midWare:TD1;
dllhandle:thandle;
pro:Tzigbee1;
begin
dllhandle:LoadLibrary('SharedLib.dll');
try
@pro:=getprocAddress(DllHandle,'zigbee1');
if assigned(@pro) then
begin
pro(midWare);
memo1.lines.add(floattostr(midware.elt1))
end;
finally
freeLibrary(dllhandle);
end;
end;
我单步调试,程序运行到最后一句都没有错,再执行 就报刚刚的内存突冲。哪位高手给解答一下嘛,急死了。
我把我所有的分都拿出来了,如果解决了,我去挣分再给您补多一些。不胜感激;
解决方案 »
- 请问exescope的rc文件的文字如何转换?
- 如何把分公司每天的SQL SVR上的数据传到总公司的SQL SVR上 ?
- 如何让针式打印机一直打印,不自动换页
- 有关MSComm控件的问题
- 在线等:怎么样在delphi里面把一个存储过程写到sql-2000的master数据库里面???
- 为什么找不到orbpas.dcu文件?
- delphi6 ado+sql2000遇到的问题,与您探讨.
- 有哪位大虾用delphi开发过网络游戏的外挂程序? 希望能指点一二!!请问哪有可用来获取可执行文件(如EXE,DLL,SYS文件)的输出函数的工
- 怎么将char数组的内存首地址保存到smallint型变量中
- 根据IP,如何获得该IP的网络名?
- delphi 权限问题
- 搞定DELPHI编程+AspWebIIS局域网版本的升级方式与大家分享一下
如果是指针类型的record,就要先申请内存
begin
pro(midWare);
memo1.lines.add(floattostr(midware.elt1))
pro(midWare);
memo1.lines.add(floattostr(midware.elt1))
pro(midWare);
memo1.lines.add(floattostr(midware.elt1))
end;
但你这里有几个错误,需要注意
1:
implementation
procedure DAQ1;external 'SharedLib.dll';这句话的意思是,静态加载DLL,引用输出函数‘DAQ1’,所谓静态加载,指的是在程序启动的时候,就自动加载DLL,在程序结束的时候自动卸载DLL,在寻找DLL的时候大致按照以下路径去搜寻:程序启动路径(程序启动路径可能和程序所在路径不同),系统的环境变量PATH中定义的各个路径(着其中包括SYSTEM32,Windows,program and files,等,一些系统路径在64bit系统下会被自动重定向)。如果你的DLL输出函数名称不等于你声明的函数名 需要用name指示字来指定你搜需的DLL输出函数。如果你的DLL是使用C来编写的,需要指示字cdecl来指定调用参数的顺序。同一个动态链接库,只能被一个进程加载一次。所以如果你已经静态加载了DLL,就不要再显示卸载该DLL,否则会在程序退出时报错,也就是说 freeLibrary(dllhandle); 这句话不要调用。但dllhandle:=LoadLibrary('SharedLib.dll');这句话调用不会出错,因为该函数实现中会先寻找有没有加载该DLL的句柄,如果已经加载,就立即返回句柄,不会重复加载。2:
DLL中如果你需要传递结构体的话,你在DELPHI中应该声明结构体指针,而不是直接使用结构体变量。
我不清楚你DLL中如何处理结构体参数的,但一般C在处理结构体的时候会有以下惯例,使用结构体指针,在函数内部初始化结构体,并赋值,返回结构体的内存大小,另外再提供释放结构体的函数,供使用完值后释放内存。或者,由外部传入一个已经初始化好的结构体,传入结构体的大小,函数内部只负责赋值,由外部负责结构体的释放。对于DELPHI中,如果在函数中声明了一个结构体变量,而非结构体指针,这种情况下,编译器会自动为结构体初始化内存,在函数退出时自动释放结构体,无需手动管理。这种机制,也可能会引起楼主提到的异常。我没有看到楼主完整的代码,以上只是我的猜想。
总结起来是:
如果传递结构体,请使用指针,并注意内存管理。
如果DLL是C实现的,请在声明函数类型的时候使用指示字cdecl
如果是静态加载的,则不需要显示释放DLL
今天去和一高手请教了下,最后把问题解决了,我们解决问题的过程和你讲的很多很相近,
最后我们在Labview里重新生成DLL,直接返回值,没有用结构体来传递值,最后调用成功。所以我们怀疑是他们生成的Dll的问题,因为要与硬件进行数据交互。但是我还是感谢您的回答。分全给您吧!因为你讲的这些,正是我昨天没有搞明白的,最近用delphi都是边学边用,所以有好多问题搞的一知半解的。