delphi调用C动态库出问题,求救?

jakefj 2017-01-04 09:55:13
C动态库函数
int CIM_SetCommPara(tDevReturn* p_psStatus) ;
tDevReturn数据结构
typedef struct
{
int iLogicCode; // 逻辑错误码
int iPhyCode; // 物理错误码
int iHandle; // 处理方法:0-不处理 1-初始化 2-重发命令
int iType; // 错误类型:0-警告 1-严重

char acDevReturn[128]; // 硬件返回信息
char acReserve[128]; // 保留信息
} tDevReturn;

delphi调用c动态库函数写法
type
TtDevReturn = record
iLogicCode: integer;
iPhyCode: integer;
iHandle: integer;
iType: integer;
acDevReturn: array[0..127] of char;
acReserve: array[0..127] of char;
end;
function CIM_SetCommPara(var p_psStatus: TtDevReturn): integer; stdcall; external 'BillDepositDevDll.dll';

procedure TForm1.Button1Click(Sender: TObject);
var
I: integer;
tDevReturn: TtDevReturn;
begin
I := CIM_SetCommPara(tDevReturn);
if I <> 0 then
begin
end;
end;
...全文
2036 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
jakefj 2017-11-13
  • 打赏
  • 举报
回复
问题解决了。主要对方给的文档有问题。定义的一个以数组为数组的变量。但是又没有说明。
leeky 2017-08-29
  • 打赏
  • 举报
回复
声明类型: PTtDevReturn = ^TtDevReturn; …… 引入函数: function CIM_SetCommPara(p_psStatus: PTtDevReturn): integer; stdcall; external 'BillDepositDevDll.dll'; …… 调用(取地址): I := CIM_SetCommPara(@tDevReturn); 以上是正确的写法,但不一定能解决你的问题。 如不能确认函数名,可用tdump查一下。 我不知你其它方面是否还有问题,最好有VC的DLL的实现代码、调用例子等, 我在近一年花了些时间用Delphi调用VC的DLL,用VC调用Delphi的DLL,感觉不同语言间调用DLL很麻烦的。尤其VC6是“满肚子的不合时宜”,甚至跟自己的操作系统闹别扭。
a442417164 2017-08-26
  • 打赏
  • 举报
回复
函数里面的结构体要传指针。
processsystem 2017-08-26
  • 打赏
  • 举报
回复
哪里来的ntdll.dll??
  • 打赏
  • 举报
回复
用sizeof看看 c里的结构体大小 和delphi是不是一样 是不是要用packed record
zhujinqiang 2017-05-25
  • 打赏
  • 举报
回复
__cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要注意了,只有用相同的方法才能够调用成功.另外,像printf这样接受可变个数参数的函数只有用cdecl才能够实现. _cdecl 是C Declaration的缩写,表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。 _stdcall 是Standard Call的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retn X,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。 _fastcall 是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。 _thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。 _fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。 C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认的调用方式可以在IDE环境中设置。 参考: http://www.cnblogs.com/youngforever/articles/3169123.html
zhujinqiang 2017-05-25
  • 打赏
  • 举报
回复
引用 8 楼 rocklee 的回复:
char, ansichar 数据对齐 stdcall C那边传入的类型是指针,delphi这边....
总结的很全面。
OK_boom 2017-05-15
  • 打赏
  • 举报
回复
char, ansichar 数据对齐 stdcall C那边传入的类型是指针,delphi这边....
santiaodahan 2017-01-05
  • 打赏
  • 举报
回复
报这个错误应该不是这里贴出的代码导致的了。应该缩小范围,分步骤排除。比如输出调试信息,定位出错的代码行。或换其他环境编译,排除代码本身的问题。如果排除代码错误,那就是IDE的问题,或安装的组件导致的,卸载组件或重新安装IDE。如果是系统文件损坏,可以运行sfc命令修复ntdll.dll。
看那山瞧那水 2017-01-05
  • 打赏
  • 举报
回复
如果是D7以上版本,Char改成AnsiChar
  • 打赏
  • 举报
回复
这个DLL用其他语言调用正常吗(在同样的系统下),或者是你使用方式的问题,调用CIM_SetCommPara之前可能需要调用某些初始化函数?
lyhoo163 2017-01-04
  • 打赏
  • 举报
回复
二者需要数据结构(内存)要一致。
jakefj 2017-01-04
  • 打赏
  • 举报
回复
suiyunonghen 你说的我都去改过,但是结果一样是报错:--------------------------- Debugger Exception Notification --------------------------- Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 7C939AF2 in module 'ntdll.dll'. Write of address 00000010'. Process stopped. Use Step or Run to continue. --------------------------- OK Help ---------------------------
不得闲 2017-01-04
  • 打赏
  • 举报
回复
看了一下,你的C函数申明为 int CIM_SetCommPara(tDevReturn* p_psStatus) ;没有带上CStdcall的标记,那么C语言默认是使用的Cdecl的调用模式,所以你的Delphi的哈数申明应该是 cdecl而不是 stdcall,另外看你的Delphi版本,如果是2007之后的Delphi,你那个char acDevReturn[128]; 这种应该申明为array[0..127] of AnsiChar

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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