[英]Delphi and C/C++ DLL
我有一个使用BTMemoryModule并从DLL导入/调用函数的delphi应用程序。 DLL是用C / C ++编写的。
delphi应用程序将原始的pwidechar(4字节数组或widechars数组)发送给函数。
我没有C / C ++伪代码,但它看起来像这样:
type
TMyFunc = function ( p : pointer ): pointer; stdcall;
procedure anynamehere();
var
Addr : TMyFunc;
MyString : WideString;
begin
[...]
Addr := BTMemoryGetProcAddress('mydll.dll', 'ExportedFunc');
MyString := 'TEST';
[...]
ExportedFunc (pwidechar(MyString));
MessageBoxW (0, pwidechar(MyString), '', 0);
end;
DLL现在应该具有指向MyString var的原始指针。 delphiapp中的过程保持活动状态(直到DLL ExportedFunc完成)。 因此,在过程结束后,不会处理MyString var。 我现在的问题是:是否可以在DLL中更改MyString的值? (技术上可行...)但是如何? 该字符串以null结尾,因此用户知道指针的长度。 但是,如果C ++ DLL更改了值,用户是否还没有分配新的空间? 还是自动发生?
谢谢你的帮助。
欢迎DLL根据需要更改指向的内存,并且它也不需要知道MyString
的地址。 它只需要知道存储在 MyString
的地址,这正是您已经传递给它的地址。 由于该函数收到一个指向以null终止的WideChar
值数组的指针,因此应这样声明该函数:
void* __stdcall ExportedFunc(wchar_t* arg);
它可以使用wcslen
找出缓冲区的长度,然后以通常的方式修改缓冲区的内容。 例如:
{
size_t const len = wcslen(arg);
for (size_t i = 0; i < len; ++i)
if (arg[i] == 'a')
arg[i] = 'e';
return 0;
}
您可以根据需要让它返回其他指针值,但是由于调用方会忽略它,因此在这种情况下并不重要。
当调用者为MyString
分配值时,操作系统将通过SysAllocString
代表程序自动分配空间。 然后,调用者将该缓冲区传递给DLL,然后DLL可以对其进行修改。 调用者之后不需要对缓冲区做任何特殊的事情。 当调用函数结束并且MyString
超出作用域时,Delphi将自动调用SysFreeString
。
您还可以删除PWideChar
类型PWideChar
并声明该函数以在Delphi中接收WideString
,在C ++中为BSTR
。 除了使用SysStringLen
而不是wcslen
之外,您还可以在DLL中进行所有相同的字符串操作。 您可以将MyString
直接传递给该函数:
ExportedFunc(MyString);
C ++代码可以更改传入的pwidechar数组的内容,但不能更改delphi理解的字符串的长度,因为C ++代码本身无法理解delphi样式的字符串。 它收到的只是一个wchar *
参数。
如果要对字符串进行重大更改(例如,使其更长),则需要使用SetLength(MyString, size)
在调用程序中分配至少与您所需的空间一样的SetLength(MyString, size)
,然后检查返回的长度,因此然后SetLength(MyString, retSize)
在字符串上调用SetLength(MyString, retSize)
以使其成为返回的大小。
同样,通常会针对缓冲区溢出等问题做出警告。
我注意到该函数返回一个指针。 如果C ++代码使用new()
分配内存,则由于两个内存分配系统不同,因此无法通过Delphi代码管理此内存。
DLL传递了一个指向缓冲区的指针。 DLL完全有可能修改该缓冲区。 DLL可以修改您的代码传递给它的4个宽字符中的任何一个。 它还可以修改第五个字符,即空终止符。
但是,DLL无法创建新缓冲区,并且调用代码无法看到该新缓冲区。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.