我有一个用C编写的遗留DLL,它包含一个返回字符串的函数,我需要从Delphi访问这个函数。 我对DLL的唯一信息是用于访问函数的VB声明:
公共声明函数DecryptStr Lib“strlib”(Str As String)As String
我试过以下没有成功:
宣言:
function DecryptStr(s: PChar): PChar; cdecl; external 'strlib.dll';
用法:
var p1, p2 : pchar; begin GetMem( p1, 255 ); StrPCopy( p2, 'some string to decrypt' ); p1 := DecryptStr( p2 ); end;
这始终使DLL与访问冲突崩溃。 我很茫然。
有什么建议 ?
考虑重写您的测试代码,如下所示:
var p1, p2 : pchar; begin GetMem( p1, 255 ); // initialize GetMem( p2, 255 ); StrPLCopy( p2, 'some string to decrypt', 255 ); // prevent buffer overrun StrPLCopy( p1, DecryptStr( p2 ), 255); // make a copy since dll will free its internal buffer end;
如果在调用DecryptStr时仍然失败,请仔细阅读https://support.microsoft.com/kb/187912 。
p2未初始化。 StrPCopy将字符串复制到随机存储器位置。 而且很可能调用约定是stdcall。
我在这里猜,但你确定它是cdecl吗? 如果VB声明没有提到它,我认为它实际上是一个STDCALL函数(STDCALL在Windows上很常见,因为几乎所有的本机API都使用它)。 调用一个调用约定的函数就像它是另一个调用约定一样,实际上可能会使堆栈陷入困境,通常会导致崩溃。
另外,请务必检查字符串是ANSI(LPSTR / LPCSTR)还是UNICODE(LPWSTR / LPCWSTR)。 我不知道VB或Delphi,所以我不知道每个人默认使用什么。
正如Jozz所说,p2(你将你的字符串复制到的地方)从未在你的例子中初始化。
试试这个。
var p1, p2 : pchar; begin GetMem( p2, 255 ); // allocate memory for 'some string...' StrPCopy( p2, 'some string to decrypt' ); p1 := DecryptStr( p2 ); end;
此外,通过调用Getmem(p1,…)分配的内存将被泄露,因为p1被DecryptStr返回的函数覆盖。
但是,我有点担心DecryptStr正在返回什么,以及谁拥有p1指向的内存。 如果它返回指向DLL分配的内存的指针,则需要注意释放内存的方式。
我同意CesarB,尝试使用stdcall指令声明它:
function DecryptStr(s: PChar): PChar; stdcall; external 'strlib.dll';
如果它不起作用,请在此处发布VB声明。
在这种情况下,最好的方法是调试程序并在执行回调之前和之后检查堆栈。 怎么知道,它甚至可能是外部DLL中的错误?
通过这种方式,您将看到如何纠正这一点非常容易。
用于与Delphi一起使用的任何机会是用Borland C或C ++ Builder编写的dll吗? 在这种情况下,它可以使用pascal指令进行编译。
字符串必须“初始化”的建议似乎是正确的。 这是因为C将要求传入的字符串以空值终止。 检查文本结尾后缓冲区中的字符是否为空(#0)。
为什么你认为传入的字符串恰好是255个字符长? 您需要为p1中的字符分配长度(p1)+ 1个字节,并在末尾分配#0个字符。
此外,您的代码示例似乎对p1和p2的使用感到困惑。 看起来p1是传递给您分配的C DLL的缓冲区,而p2是DLL分配的返回字符串。 但那么代码就是(注意使用p1和p2)
var p1, p2 : pchar; begin GetMem( p1, 255 ); StrPCopy( p1, 'some string to decrypt' ); p2 := DecryptStr( p1 ); end;
更好的变量名称可以帮助您更清楚。
我正在放弃我的解决方案,因为我已经开始使用它并且没有在任何答案中找到它。
C ++函数如下所示:
int __stdcall DoSomething(char * _name);
为了使它在Delphi中工作,我声明了以下函数
function DoSomething(name: PAnsiChar): integer; stdcall; external 'somedll.dll';
然后当我拨打电话时,我有一个看起来像这样的function:
var s: PAnsiChar; begin GetMem(s, 255); DoSomething(s); // s now contains the value returned from the C DLL end;
我尝试过使用PChar而不是PAnsiChar但我得到的只是垃圾。 另外,如果我在Delphi中声明函数并将参数设置为var ,那么当我尝试读取它时会出现exception。
希望这有助于任何人..
以上就是c/c++开发分享从Delphi中的C DLL获取字符串返回值相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/544838.html