调用delphi的dll问题,急等!!!!!!
我调用别人用delphi写的读卡的dll,只要读卡有返回值的时候就肯定报access invalid....错误,分析下很有可能是读卡返回的值写入我分配的变量时出错.下面是我的代码:
void __fastcall TForm1::Button3Click(TObject *Sender)
{
FARPROC P;
char* recstr[100];
OPENPORT openport = (OPENPORT)::GetProcAddress(hMf,"OpenPort");
int i =openport(1,19200,100,1,"ffffffffffff","010203040506");
ShowMessage(IntToStr(i));
P = GetProcAddress(hMf,"ReadSn");
if(P != NULL)
{
READSN = (int (__stdcall *)(char*)) P;
READSN(*recstr);
ShowMessage(*recstr);
}
else
{
ShowMessage("error");
}
对方dll中的函数为:ReadSn(var sn:PChar):Integer:stdcall
跪求哪位大大给指正错误,不吝惜分......
[最优解释]
我猜想dll应该需要你传进去一个接收数据的缓存区地址。
而你原来的定义:char* recstr[100]; 是定义了一个指针数组,相当于定义了100个指针变量,recstr[0],recstr[1], ...recstr[99]都是指针变量,这些数据元素(指针变量)的值都是未知的,即指针没有明确的指向。
表达式 *recstr 和recstr[0]是等价的,表示访问recstr[0]的值,前面说过recstr[0]是一个指针变量,但是它指向哪里呢?不知道,因为你没有给它明确的指向,把recstr[0]的值传值递给dll,就是把一个未知的地址值传递给了dll,dll再把数据放进去这个未知的地址不出错才怪呢。
把这两行代码改改试试:
char* recstr[100];
...
READSN(*recstr);
改为:
char recstr[100];
...
READSN(recstr);
[其他解释]
既然ReadSn的参数是一个char *,你直接将recstr代入就行了。如:
READSN(recstr);
[其他解释]
char recstr[100];
READSN(recstr);
ShowMessage(recstr);
[其他解释]
自己先顶一下,别掉了,真着急啊
[其他解释]
个人觉得 ,你应该去google 和baidu上面查一下 关键字 : C++ builder中怎么调用delphi的DLL 或
C++ builder中怎么调用delphi的动态库
[其他解释]
啊,谢特。4楼言之有理,刚看到楼主的代码里居然是定义了100个char *指针,不AV才怪。
[其他解释]
谢谢大家帮助。
刚刚试了一下,开始没问题,几次操作以后又是AV错误了....
头疼...
[其他解释]
列为大大,再给指正一下。
程序哪里都没改动啊....
[其他解释]
这是改正过的:
FARPROC P;
AnsiString rec;
char recstr[100];
OPENPORT openport = (OPENPORT)::GetProcAddress(hMf,"OpenPort");
int i =openport(5,19200,100,1,"ffffffffffff","010203040506");
ShowMessage(IntToStr(i));
P = GetProcAddress(hMf,"ReadSn");
if(P != NULL)
{
READSN = (int (__stdcall *)(char*)) P;
int ii = READSN(recstr);
ShowMessage(IntToStr(ii));
ShowMessage(recstr);
}
else
{
ShowMessage("error");
}
置红的一行开始读取很正常,几次以后再次AV。
求助各位....
[其他解释]
memset(recstr,0,sizeof(recstr));//加上这句试试
int ii = READSN(recstr);
别的也看不出什么问题了
[其他解释]
发现了,是定义的char数组被占用,重新定义char数组就没事儿。应该是以前char数组分配的那部分内存没有释放,仍然被占用出错。
[其他解释]
上面的没说完,我动态分配了一个数组也会出AV错误。即使在结束的时候delete掉。
[其他解释]
看看缓冲大小是否合适。有没有可能溢出。
[其他解释]
分配的缓冲大小没问题,用自带的demo读取没问题(demo是delphi的)
var
p:PChar;
card_sn:string;
begin
Open_Port;
GetMem(p,100); //给指针分配内存
if ReadSn(p)<>0 then
begin
ClosePort;
Application.MessageBox('寻卡失败!','错误',MB_OK+MB_ICONERROR);
exit;
end;
card_sn:=p;
Memo1.Lines.Add(#13#10+'卡序列号:'+card_sn);
FreeMem(p); //释放内存
ClosePort;
end;
上面的是demo程序
[其他解释]
一开始正常,后来几次出错,是不是Open了Port以后没有关闭?
[其他解释]
能关的都关了。dll也释放了。
如果还是不行,就只能重启电脑试了。
[其他解释]
关闭串口的函数我另外放在一个button里了,每次我都会手动关闭串口的。这个没有问题。
[其他解释]
你先定义数组大一点试试,比如110个元素。如果DLL正好有100字节的话,就没有地方存结尾符了。
另外delphi代码里有OpenPort 和对应的ClosePort
但你的Cb代码里只调用openport,没有调用ClosePort函数,端口不断打开,而不关闭,以后还可以正常使用?奇怪。
建议lz把代码梳理一下:
1.把获取dll函数接口的代码独立写在一个函数里,程序调用一次就行了,没有必要每次都要查找接口。
2.打开端口,关闭端口要匹配,最好开始打开一次,以后多次读写,退出时,或再不需要读写端口了,再关闭端口。
[其他解释]
多谢各位大大的帮助。现在解决问题了。
把定义改成 int (__stdcall *)(char**)
这样就通过了,调用的参数:
char* recstr;
ReadSn(&recstr);
[其他解释]
错误的提示和刚开始一模一样吗?包含invalid后面的内存。
想不出来哪儿有问题,你做好把Cb代码的处理过程做的和demo一模一样,组件、按钮、事件过程等都完全一样,看会不会出错。
[其他解释]
确实很诡异。
[其他解释]
很奇怪了,dll自己申请内存吗?什么时候释放呢? lz小心内存泄露。
从delphi例子看应该不是dll分配内存啊。