TFileStream Read() 和 Write() 从和到 c 样式字节/字符缓冲区[]

问题描述 投票:0回答:1

我刚刚安装了 C++ Builder 12,想要编译一个古老的软件,它使用 TFileStream 来读取和写入 C 风格的缓冲区。例如:

DWORD MyFileStream::Read (BYTE *Buffer, DWORD Count)
{
try
    {
    if (File)
        return File->Read(Buffer, Count) ;
    }
catch(...)
    {
    LastError = GetLastError() ;
    return MY_ERROR_READ ;
    }
return 0x00 ;
}

这在 32 位中仍然可以正常编译,但是(从 c++ Builder 11.3 到 12)它现在不再在 64 位中编译。 所以,大约 20 年后,我不得不去查看帮助文件中的 TFileStream,它似乎只使用 DynamicArray ?

困惑? 那为什么它编译成32位呢? 我感觉帮助文件不完整? 更重要的是,如何在不创建动态数组的情况下解决这个问题(假设仍然可能)?

错误:

call to member function 'Read' is ambiguous
[C++ Error] System.Classes.hpp(1756, 36):  candidate function
[C++ Error] System.Classes.hpp(1771, 38):  candidate function
[C++ Error] System.Classes.hpp(1777, 36):  candidate function not viable: no known conversion from 'BYTE *' (aka 'unsigned char *') to 'System::Sysutils::TBytes &' (aka 'DynamicArray<unsigned char> &') for 1st argument
[C++ Error] System.Classes.hpp(1779, 38):  candidate function not viable: no known conversion from 'BYTE *' (aka 'unsigned char *') to 'System::Sysutils::TBytes &' (aka 'DynamicArray<unsigned char> &') for 1st argument
[C++ Error] System.Classes.hpp(1773, 36):  candidate function not viable: requires 3 arguments, but 2 were provided
[C++ Error] System.Classes.hpp(1775, 38):  candidate function not viable: requires 3 arguments, but 2 were provided
c++builder
1个回答
1
投票

所以,大约 20 年后,我不得不去查看帮助文件中的 TFileStream,它似乎只使用 DynamicArray ?

这是不正确的。它仍然具有使用原始缓冲区的重载。

真正的罪魁祸首是

Read()
(和
Write()
)仅在64位下有额外的重载,这些重载尚未记录,但如果你查看
System.Classes.hpp
中的声明,你会看到它们:

public:
    virtual System::LongInt __fastcall Read(void *Buffer, System::LongInt Count)/* overload */;
    virtual System::LongInt __fastcall Write(const void *Buffer, System::LongInt Count)/* overload */;
#ifdef _WIN64
    virtual System::NativeInt __fastcall Read(void *Buffer, System::NativeInt Count)/* overload */;
    virtual System::NativeInt __fastcall Write(const void *Buffer, System::NativeInt Count)/* overload */;
#endif /* _WIN64 */
    virtual System::LongInt __fastcall Read(System::Sysutils::TBytes Buffer, System::LongInt Offset, System::LongInt Count)/* overload */;
    virtual System::LongInt __fastcall Write(const System::Sysutils::TBytes Buffer, System::LongInt Offset, System::LongInt Count)/* overload */;
#ifdef _WIN64
    virtual System::NativeInt __fastcall Read(System::Sysutils::TBytes Buffer, System::NativeInt Offset, System::NativeInt Count)/* overload */;
    virtual System::NativeInt __fastcall Write(const System::Sysutils::TBytes Buffer, System::NativeInt Offset, System::NativeInt Count)/* overload */;
#endif /* _WIN64 */
    System::LongInt __fastcall Read(System::Sysutils::TBytes &Buffer, System::LongInt Count)/* overload */;
    System::LongInt __fastcall Write(const System::Sysutils::TBytes Buffer, System::LongInt Count)/* overload */;
#ifdef _WIN64
    System::NativeInt __fastcall Read(System::Sysutils::TBytes &Buffer, System::NativeInt Count)/* overload */;
    System::NativeInt __fastcall Write(const System::Sysutils::TBytes Buffer, System::NativeInt Count)/* overload */;
#endif /* _WIN64 */

这意味着仅在 64 位下,您尝试调用的 2 参数

Read()
现在接受
LongInt
NativeInt
类型作为缓冲区大小,并且因为
DWORD
可以隐式转换为这两种类型,这就是为什么您的代码现在在 64 位下不明确,但在 32 位下不明确。

要解决此问题,您需要通过将

DWORD
类型转换为所需类型来显式告诉编译器要调用哪个重载。

© www.soinside.com 2019 - 2024. All rights reserved.