Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Visual Studio MFC中的Delphi WideString_C++_Visual Studio 2010_Delphi_Mfc - Fatal编程技术网

C++ Visual Studio MFC中的Delphi WideString

C++ Visual Studio MFC中的Delphi WideString,c++,visual-studio-2010,delphi,mfc,C++,Visual Studio 2010,Delphi,Mfc,我正在尝试从一个用Delphi编写的EXE接收信息。EXE向我传递指向其数据结构之一的指针: Type RecordType = Record St: WideString; Next: Pointer; End; Var DataRec: ^RecordType; 因此,在Visual Studio MFC中,我声明了一种类似的数据类型: struct RecordRec { BSTR St; void *Next; }; RecordRec *D

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

Type
  RecordType = Record
    St:   WideString;
    Next: Pointer;
  End;

Var
  DataRec: ^RecordType;
因此,在Visual Studio MFC中,我声明了一种类似的数据类型:

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

RecordRec *DataRec;
Delphi帮助说明WideString与BSTR兼容,但是,这不起作用。当我在调试模式下查看St时,它会说

"0x0000000000000000 <Bad Ptr>   wchar_t *"
但这不适用于WideString,我真的不认为我应该声明一个包含~2^30 1073741824个字符的变量


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

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

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

因此您有两个不同的流程-Delphi一个DP和VS一个VSP。每个都有自己的地址空间,DP中的有效指针在VSP中无效。这就是为什么会有例外?出现了

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

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


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

所以您有两个不同的流程-Delphi一个DP和VS一个VSP。每个都有自己的地址空间,DP中的有效指针在VSP中无效。这就是为什么会有例外?出现了

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

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

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

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

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

从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的包装器,但这并不意味着原始BSTR指针可以按原样从一个进程传递到另一个进程。它的数据在跨越流程边界时必须进行编组。COM通常会自动处理,但手动传递原始BSTR指针不会

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

从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...

指针。。。。在谁的地址空间?用什么方法发送指针?非常复杂。首先是有一个Windows服务。该服务在Windows启动时自动启动和运行。当Delphi EXE运行时,它调用作为服务一部分的DLL中的函数,并向服务传递指向其数据的指针。然后,VisualStudioMFC程序调用服务中的函数以获取指针的副本。然而,当它到达我的MFC程序时,我看到坏的Ptr。当使用短字符串时,这一切都会起作用,但后来事情被更新为宽字符串,我不知道MFC中的等效声明是什么。它们至关重要。向DLL传递WideString类型/从DLL传递WideString类型是正确的方法,但请描述所有情况。我可以控制服务和MFC程序,但我不能控制Delphi EXE
调用DLL函数时,该DLL将数据发送到另一个进程。这意味着DLL需要将数据序列化为可以安全地跨进程边界传递,然后在另一端取消序列化的格式。短字符串可以按原样安全地传递,因为它是易于复制的固定长度内存块。但是BSTR不能,它必须被封送。指针仅在分配它们的进程上下文中有效。无法跨进程边界传递指针。指针。。。。在谁的地址空间?用什么方法发送指针?非常复杂。首先是有一个Windows服务。该服务在Windows启动时自动启动和运行。当Delphi EXE运行时,它调用作为服务一部分的DLL中的函数,并向服务传递指向其数据的指针。然后,VisualStudioMFC程序调用服务中的函数以获取指针的副本。然而,当它到达我的MFC程序时,我看到坏的Ptr。当使用短字符串时,这一切都会起作用,但后来事情被更新为宽字符串,我不知道MFC中的等效声明是什么。它们至关重要。向DLL传递WideString类型/从DLL传递WideString类型是正确的方法,但请描述所有情况。我可以控制服务和MFC程序,但我不能控制Delphi EXE。因此,您有一个进程正在调用DLL函数,而该DLL正在将数据发送到另一个进程。这意味着DLL需要将数据序列化为可以安全地跨进程边界传递,然后在另一端取消序列化的格式。短字符串可以按原样安全地传递,因为它是易于复制的固定长度内存块。但是BSTR不能,它必须被封送。指针仅在分配它们的进程上下文中有效。你不能跨越进程边界传递指针,但我知道在Delphi端它不是空的。我一直在测试它,并填写一个我希望在MFC端看到的值。然后你的问题就在别处了。你在问题中提供的东西没有问题。但我知道在德尔福方面它不是空的。我一直在测试它,并填写一个我希望在MFC端看到的值。然后你的问题就在别处了。您在问题中提供的内容没有问题。@RudyVelthuis:您误读了该文档。BSTR由COM函数分配,使用集中式系统内存管理器,这是WideString不如UnicodeString效率的原因之一,但数据本身驻留在分配应用程序的地址空间中,就像它分配的任何其他内容一样。您可以将BSTR传递给接受wchar_t*作为输入的应用程序的任何函数,该函数将直接访问字符数据。所讨论的Delphi应用程序正在调用一个DLL函数,该函数正在将数据传递给一个单独的服务进程。var b:BSTR;b:=系统分配字符串“测试”;MessageBoxW0,PWideCharb,MB_正常;SysFreeStringb;如果请求分配BSTR的应用程序进程的地址空间中没有BSTR数据,则该代码将无法运行。COM是否是使用的内存管理器并不重要,就像Delphi字符串是否使用BorlandMM vs FastMM vs ScaleMM分配一样。分配的数据驻留在调用应用程序的内存地址空间中,因此可以对其进行访问,并由内存管理器跟踪,以便以后可以正确释放。如果BSTR驻留在COM本身的系统层,则无需封送就可以跨进程边界传递BSTR,可以像HWND can一样传递BSTR指针。但事实并非如此,因为BSTR指针没有全局作用域,它们有进程作用域,就像大多数内存分配一样。因此,需要跨进程边界将BSTR数据从一个地址空间封送到另一个地址空间。@RudyVelthuis:您误读了该文档。BSTR由COM函数分配,使用集中式系统内存管理器,这是WideString不如UnicodeString效率的原因之一,但数据本身驻留在分配应用程序的地址空间中,就像它分配的任何其他内容一样。您可以将BSTR传递给接受wchar_t*作为输入的应用程序的任何函数,该函数将直接访问字符数据。所讨论的Delphi应用程序正在调用一个DLL函数,该函数正在将数据传递给一个单独的服务进程。var b:BSTR;b:=系统分配字符串“测试”;MessageBoxW0,PWideCharb,MB_正常;SysFreeStringb;如果请求分配BSTR的应用程序进程的地址空间中没有BSTR数据,则该代码将无法运行。COM是否是使用的内存管理器并不重要,就像Delphi字符串是否使用BorlandMM vs FastMM vs ScaleMM分配一样。分配的数据驻留在调用应用程序的内存中
地址空间,以便可以访问,并由内存管理器跟踪,以便以后可以正确释放。如果BSTR位于系统层的COM内部,则不需要封送就可以跨进程边界传递BSTR,BSTR指针可以像HWND一样传递。但事实并非如此,因为BSTR指针没有全局作用域,它们有进程作用域,就像大多数内存分配一样。因此,需要跨进程边界将BSTR数据从一个地址空间封送到另一个地址空间。@Rudy Velthuis我明白了,但作者写道:EXE将**指针**传递给我,指向其中一个数据结构,并显示^RecordTypetype@RudyVelthuis我明白了,但作者写道:EXE将**指针**传递给我,指向其中一个数据结构,并显示^RecordTypetype