Delphi调用DLL遇阻:C函数与结构体转换后调用返回0求助
问题分析与修正方案
你的核心问题在于结构体内存布局不匹配、类型定义错误以及参数传递方式不正确,导致DLL无法正确解析传入的数据,最终返回无效句柄。以下是具体修正步骤:
一、错误点总结
- 结构体使用了Delphi动态数组(
array of Byte),但C语言中是固定大小的静态数组,两者内存布局完全不同,DLL无法识别。 - C的
ULONG是无符号32位整数,你误用了有符号的Longint,可能导致数据解析异常。 - 函数参数语法错误,且未正确传递结构体的指针地址。
- 字符串赋值未考虑C端的ANSI编码要求,且未初始化结构体,残留垃圾数据干扰解析。
二、修正后的类型与函数声明
严格匹配C语言的内存布局与类型定义:
// 对应C的ULONG(无符号32位整数) type ULONG = Cardinal; // 严格对齐C的结构体,packed保证内存布局完全一致 DAPI_OPENMODULEEX_STRUCT = packed record address: array[0..255] of Byte; // 固定256字节数组,对应C的unsigned char address[256] timeout: ULONG; // 对应C的ULONG timeout portno: ULONG; // 对应C的ULONG portno encryption_type: ULONG; // 对应C的ULONG encryption_type encryption_password: array[0..31] of Byte; // 固定32字节数组,对应C的unsigned char encryption_password[32] end; PDAPI_OPENMODULEEX_STRUCT = ^DAPI_OPENMODULEEX_STRUCT; // 结构体指针类型 // 函数声明(调用约定假设为stdcall,多数Windows DLL使用该约定;若DLL实际为cdecl,需替换) function OpenModuleEx( moduleID: ULONG; nr: ULONG; exbuffer: PDAPI_OPENMODULEEX_STRUCT; open_options: ULONG ): ULONG; stdcall; external 'master.dll';
三、正确的调用代码
var buffer: DAPI_OPENMODULEEX_STRUCT; lhandle: ULONG; sAddr: AnsiString; begin // 1. 清零结构体,避免垃圾数据干扰DLL解析 FillChar(buffer, SizeOf(DAPI_OPENMODULEEX_STRUCT), 0); // 2. 设置IP地址:转为ANSI字符串后复制到静态数组 sAddr := '10.241.0.147'; if Length(sAddr) > 255 then sAddr := Copy(sAddr, 1, 255); // 防止超出数组长度 Move(sAddr[1], buffer.address[0], Length(sAddr)); // 数组剩余位置已被清零,自动形成C风格的字符串结尾 // 3. 设置其他参数 buffer.portno := 9912; buffer.timeout := 5000; buffer.encryption_type := 0; // 密码为空时无需额外操作,FillChar已将数组清零 // 4. 调用DLL函数,传递结构体指针 lhandle := OpenModuleEx(42, 0, @buffer, 0); // 检查调用结果 if lhandle = 0 then ShowMessage('OpenModuleEx调用失败,返回句柄为0') else ShowMessage(Format('OpenModuleEx调用成功,句柄:%u', [lhandle])); end;
额外说明
- 调用约定:如果DLL实际使用
__cdecl调用约定,需将函数声明中的stdcall改为cdecl,否则会导致栈错误。可通过Dependency Walker工具查看DLL的导出函数调用约定。 - 64位适配:若使用64位程序,需确认C的
ULONG是否为64位(对应Delphi的UInt64),32位程序则保持Cardinal即可。
内容的提问来源于stack exchange,提问作者Stevie
相关产品推荐
相关产品推荐

