Delphi的指针功能实际上是很少有用到的,但是它对外封装了几个指针的类型还是可以用用,如
PChar (=^Char),
PPChar (=^PChar, 传说中的双指针,在Delphi5与它的以下版本可能没有这个类型,但可以自己建立,如:
type
PPChar = ^PChar
)
等等。
我也是在偶然的机会下碰到这个技术话题的。在写一个DELPHI的系统中,调用一个厂家提供的DLL(VC)时,代码类似如下:
DLL模块
- int _stdcall getInfo(char* info)
- int _stdcall getTest(char* info)
- {
- char* str = "Test";
- // TODO: str业务处理
- strcpy(info, str);
- return 0;
- }
Delphi客户端程序
- function getInfo(info: PChar): string; stdcall; External '{ Dll 函数}';
- // 测试过程
- procedure Test;
- var
- pStr: array[0..100] of Char;
- begin
- getTest(pStr);
- ShowMessage(pStr);
- end;
如上,经测试成功。
大家可能就发现问题了,Delphi这边需要申请一个内存空间,如array[0..100], 或使用strAlloc,才能调用VC提供的DLL函数。否则就会报些大家最不愿意看见的内存地址错误,如:"Access violation at address 00423A69 in module 'Demo.exe'. Read of address 74736560."。
但是大家有没有从业务功能上考虑,我怎么知道需要申请多少内存空间呢,换句话说,DELPHI调用这边就必须设个很大的空间,这样的程序设计是不是不太合理?!所以想到这,就考虑是不是应该让Dll的函数自己来申请内存空间。修改DLL:
- int _stdcall getTest(char* info)
- {
- char* str = "Test";
- // TODO: str业务处理
- info = (char*) malloc(sizeof(char) * strlen(str) + 1); // 分配内存空间
- strcpy(info, str);
- info[strlen(str)] = 0x00; // 标记结束符
- return 0;
- }
调用代码修改pStr: PChar,如;
- procedure Test;
- var
- pStr: PChar;
- begin
- getTest(pStr);
- ShowMessage(pStr);
- end;
经调用,数据是出来了,可惜是乱码,在记事本中显示为“?”,至今也搞不清为撒。那就只能考虑别的方式吧。
Delphi的PChar不是表示指针吗?那把getTest(pStr)改成getTest(@pStr)传地址进去如何,结果又报内存错误,如"Access violation at address 00403A8B in module 'Demo.exe'. Read of address 00200000."(这内存地址又换了一组)。
delphi竟然传指针过来,那DLL是不是得改一下,用双指针试试,如:
- int _stdcall getTest(char* *info)
- {
- char* str = "Test";
- // TODO: str业务处理
- *info = (char*) malloc(sizeof(char) * strlen(str) + 1); // 分配内存空间
- char* c = *info;
- strcpy(c, str);
- c[strlen(str)] = 0x00;
- return 0;
- }
delphi这边为:
- var
- pStr: PChar;
- begin
- getTest(@pStr);
- ShowMessage(pStr);
- end;
咦,还真可以了。Ok,跟厂家协定好,就这么做。双方很高兴的完成了接口的联调工作。
可是,我在仔细阅读接口文档一边又一边时,给自己提出了一个问题,将如,明年厂家更换了,更换的这个厂家如果用Delphi写这个DLL,我又不想修改现在的调用程序,那么这个DLL怎么实现?左思又询中,想到了用PPChar来代替char**, 就写出了如下的函数:
- function getTest(info: PPChar): Integer;
- var
- str: PChar;
- begin
- Result := -1; // 返回错误代码
- try
- str := 'Test';
- // TODO: str业务处理
- Info^ := strAlloc(Length(str) * SizeOf(Char) + 1); // 分配内存空间
- StrCopy(Info^, PChar(str));
- Result := 0;
- except
- end;
- end;
经多次测试,发现这样写非常的成功。我终于安心的关闭了接口文档,宣布接口联调结束。
可能大家还有疑问,如:为什么分配内存空间时VC和Delphi都要加1了?那是因为需要存储字符串结束符"/0"(其实在上面也找得到答案,见"c[strlen(str)] = 0x00;"这句代码)。
发现我们做开发的真正做进去了,冠冕堂皇的叫做"举一反三",从工作效率上讲,这叫"没事找事"。得出个名言:"世上本无事,找的人多了,也就有了事"。
本文介绍了如何在 Delphi 中使用双指针进行内存管理和数据传递,包括直接传递指针、传递指针变量地址以及使用 PPChar 类型的方法。通过示例展示了在动态分配内存和字符串处理中的应用。

1090

被折叠的 条评论
为什么被折叠?



