Delphi调用VC++的dll ( 积分: 100 )

  • 主题发起人 主题发起人 bluesky2006
  • 开始时间 开始时间
B

bluesky2006

Unregistered / Unconfirmed
GUEST, unregistred user!
我用VC++做了一个dll,想用Delphi调用它。编译通过了,但是执行时候总弹出 Access violation at address00403E58 in module 'Project1.exe'.Read of address255FFF8.这样的错误。请教各位大侠!
我的VC++的函数是:
extern "C" _declspec(dllexport) int getDate(U16* adDate)
在Delphi中的调用如下:
在Unit2中声明
interface
type
TgetDate=function( adDate:pointer):Integer; stdcall;
在Unit1中
type
pointer=^Linkdata;
LinkData=Record
num:word;
next:pointer;
end;
var
Form1: TForm1;
implementation
uses Unit2;
procedure TForm1.Button1Click(Sender: TObject);
var
getDate:TgetDate;
s,i:Integer;
Infor: pointer;
date:array[1..1000]of word;
begin
getMem(Infor,sizeof(word));
i:=1;
Handle:=LoadLibrary('PC.dll');//将“PC.dll”的文件映象映射进调用进程的地址空间
if Handle<>0 then
begin
@getDate:=GetProcAddress(Handle,'getDate');//取得DLL中函数getDate( )的地址
if @getDate<>nil then
begin
s:=getDate(Infor);
while (intToStr(Infor.num) <>'') do
begin
date:=Infor.num;
Memo1.Lines.Add(IntTostr(date));
Infor:=Infor.next;
i:=i+1;
end;
else
ShowMessage('调用函数“GetProcAddress”时出错!');
FreeLibrary(Handle); //从进程的地址空间中解除“MaxMin.dll”文件的映射
FreeMem(infor);
end;
end.
 
interface
type
TgetDate=function( adDate:pointer):Integer; cdecl;
 
动态库是在自己独立的内存空间中运行,应用程序调用都用是FAR远程调用,这样就必须约定双方的参数压栈顺序,CDECL,STDCALL等就是一个约定。
 
@getDate:=GetProcAddress(Handle,'getDate');//取得DLL中函数getDate( )的地

把里面的@都去掉试试,因为getDate本身就是指针了
 
To Mike1234567890:
没有明白您的意思,能不能再给我解释的明白点。多谢了![:)]
 
To dangde:
我刚刚试了,还是同样的错误!
 
我提出的是你犯的原则性错误。
至于你的代码问题,你的C++的代码没有贴出来,没法看。
 
我调用外部DLL的函数是这样的

先在var里声明
function getDate(adDate: Pointer): Integer;cdecl;external 'PC.DLL'

楼主试下吧,我还不知道有什么区别,只是我目前用的都没问题
 
我的VC程序是:

extern "C" _declspec(dllexport) int getDate(U16* adDate)
{
cardID = 0;
err=0;
AccessCnt = 0;
MemSize = 0;
channel=1;
sample_rate=10000; //采样频率10 KHz
ADChan=0; //采样通道是0

cardID = Register_Card(PCI_9810, Card_number);
if (cardID<0) {
AfxMessageBox("Register Card Failed!");
exit(1);
}
err=AI_ContReadChannel (cardID, ADChan, AD_B_1_V, InBuf, ScanCount,sample_rate, SYNCH_OP);
if (err!=NoError) {
AfxMessageBox("Read channel Failed!");
exit(1);
}
else{
adDate=InBuf;

}
Release_Card(cardID);
return 2;

}
 
在你的C代码函数申明中加上 stdcall,那么在delphi中就可以正常了
因为压栈方式不同, 在Delphi中 Pointer直接传递地址!C中创地二次:

var
a: pointer;
lea eax,a

char *a;
mov eax,a
mov eax,[eax]
 
不好意思,请问我把stdcall加到哪里,刚才我在头文件声明中加了,可是提示错误missing storage-class or type specifiers。
 
不一定非要改成stdcall,两边一致就行。既然你的dll中是CDECL约定,调用程序也用CDECL就好了

你的程序这几个地方有问题
1、getMem(Infor,sizeof(word)); //分配空间不够,应为getMem(Infor,sizeof(LinkData));

2、while (intToStr(Infor.num) <>'') do //还有后面好几处对Infor的使用,应该为Infor^.num的格式

另外pointer=^Linkdata;这个定义似乎换个名字好些,pointer好象是个关键字
 
To maze:

我按您的建议改过来了。但是还是会报同样的错误!
 
具体出错在那一步
你能确定你的dll完全正确么,用vc调用是否正确
 
好像是出在循环这边。VC的dll应该没有问题,我通过这个函数改做了个VC应用程序,能有数据出现。但没有用VC调用过这个dll.
 
调用约定问题
extern "C" _declspec(dllexport) int getDate(U16* adDate)
对应Delphi应该是
TgetDate=function( adDate:pointer):Integer; cdecl;
再一个你的结构指针名最好不要叫Pointer,Pointer是Delphi无类型指针的名字.

while (intToStr(Infor.num) <>'') do这行是个死循环.肯定会溢出异常的.
因为你的Num是个Word值,转换到字符串不会有为空的时候
 
谢谢,我再试试看![:)]
 
谢谢各位,我的问题解决了.不过我没有用指针.我改成数组了.
VC的声明是extern "C"_declspec(dllexport) int getDate(U16 Volt[550]);
Delphi的函数定义为 TgetDate=function(adDate:array of Word):Integer;cdecl;
 
谢谢各位的热心帮助![:)]
 
后退
顶部