Delphi WideString in Visual Studio MFC

Delphi WideString in Visual Studio MFC

本文关键字:Studio MFC Visual in WideString Delphi      更新时间:2023-10-16

我试图从用Delphi编写的EXE中接收信息。EXE向我传递一个指向其数据结构之一的指针:

Type
  RecordType = Record
    St:   WideString;
    Next: Pointer;
  End;
Var
  DataRec: ^RecordType;

因此,在VisualStudioMFC中,我声明了一个应该类似的数据类型:

struct RecordRec
{
  BSTR St;
  void *Next;
};
RecordRec *DataRec;

Delphi帮助说WideString与BSTR兼容,但这不起作用。当我在调试模式下查看St时,它显示

"0x0000000000000000 <Bad Ptr>   wchar_t *"

我不知道如何在VisualStudioMFC中声明WideString的等效项。

如果是ShortString,我会声明:

struct RecordRec
{
  BYTE StLen;
  char St[255];
  void *Next;
};

但这对WideString不起作用,我真的不认为我应该声明一个包含~2^30(1073741824)个字符的变量。

我错过了什么?我真的希望有人能帮忙。

Delphi WideString实际上是BSTR的包装器,但这并不意味着原始BSTR指针可以按原样从一个进程传递到另一个进程。它的数据在通过流程边界时必须进行整理。COM通常会自动处理,但手动传递原始BSTR指针则不会。

因此,如果您无法更改Delphi应用程序以为字符数据提供IPC安全数据块(类似于ShortString解决方法),则接收应用程序将不得不手动封送BSTR数据。它可以使用ReadProcessMemory()用于:

  • 从Delphi应用程序的地址空间中读取BSTR的长度(BSTR的字符数据以一个4字节整数为前缀,指定其在wchar_t元素中的长度)
  • 在自己的地址空间内分配指定长度的wchar_t[]数组
  • 从Delphi应用程序的地址空间将字符数据读取到其自身地址空间中的数组中

例如(为简洁起见,省略了错误处理):

RecordRec *DataRec = ...;
std::wstring DataSt;
if (DataRec->St)
{
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, TheDelphiAppProcessID);
    int len = 0;
    SIZE_T numRead = 0;
    ReadProcessMemory(hProcess, LPBYTE(DataRec->St)-4, &len, 4, &numRead);
    if (len > 0)
    {
        DataSt.resize(len);
        ReadProcessMemory(hProcess, DataRec->St, &DataSt[0], len*2, &numRead);
    }
    CloseHandle(hProcess);
}
// use DataSt as needed...

您没有遗漏任何内容。Delphi的WideString实际上相当于BSTR。您在调试器中看到的值是一个空指针。Delphi会将其视为一个空字符串;你可能应该用同样的方式对待它。

所以您有两个不同的过程-Delphi一个(DP)和VS一个(VSP)。每个都有自己的地址空间,DP中的有效指针在VSP中无效。这就是<Bad Ptr>(异常?)出现的原因。

顺便说一句,我注意到VSP中的地址是64位的。Delphi进程也是64位吗?

您需要通过共享内存进行某种进程间通信(IPC)。

因为您可以控制服务和MFC程序,所以您可以将接收到的数据保存到DLL中的命名内存映射文件中,然后MFC进程将打开它并读取数据。