c ++读取(.cso)编译的着色器对象返回\ 0

时间:2013-12-30 17:51:37

标签: c++ io directx binaryfiles vertex-shader

我尝试过两种不同的方法来读取这个cso文件。哪个是microsofts编译着色器

HRESULT BasicReader::ReadData(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr<uint8_t[]>& data, _Out_ size_t* dataSize) {
ScopedHandle hFile(safe_handle(CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)));
    LARGE_INTEGER fileSize = { 0 };
    FILE_STANDARD_INFO fileInfo;
    GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo));
    fileSize = fileInfo.EndOfFile;
    data.reset(new uint8_t[fileSize.LowPart]);
    DWORD bytesRead = 0;
    ReadFile(hFile.get(), data.get(), fileSize.LowPart, &bytesRead, nullptr);
    *dataSize = bytesRead;
}

GetFileInformationByHandleEx返回true 和ReadFile返回true

HRESULT BasicReader::ReadData(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr<uint8_t[]>& data, _Out_ size_t* dataSize) {
    std::ifstream fstream;
    fstream.open(fileName, std::ifstream::in | std::ifstream::binary);
    if (fstream.fail())
        return false;
    char* val;
    fstream.seekg(0, std::ios::end);
    size_t size = size_t(fstream.tellg());
    val = new char[size];
    fstream.seekg(0, std::ios::beg);
    fstream.read(val, size);
    fstream.close();
    auto f = reinterpret_cast<unsigned char*>(val);
    data.reset(f);
    *dataSize = size;
}

这两种方法都使数据= \ 0 然而;当我指向同一目录中的另一个文件时,它会给我数据。这里发生了什么? 这是file

我读了文件的前几个字节,就是这样:

0 2 254 255 254 255 124 1 68 66 85 71 40 0 0 0 184 5 0 0 0 0 0 0 1 0 0 0 144 0 0
0 72 0 0 0 148 0 0 0 4 0 0 0 104 5 0 0 212 2 0 0 67 58 92 85 115 101 114 115 92 
106 97 99 111 98 95 48 48 48 92 68 111 99 117 109 101 110 116 115 92 86 105 115 
117 97 108 32 8...

工作文件如下所示:

68 68 83 32 124 0 0 0 7 16 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
32 0 0 0 0 64 0 0 0 0 0 0 0 32 0 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 16
0 0 0 0 0 0 0 0 0 0...

1 个答案:

答案 0 :(得分:2)

您的代码按预期工作:char* data数组包含文件的数据。这里出现的问题是你的char* data数组被你的可视化工具误解了(无论你用什么来形象化:调试器可视化器,std::cout等)。他们都尝试打印以null结尾(c风格)的字符串,但它会立即终止,因为第一个字符为0.原始数组也可以在调试器中显示为指针:地址和仅第一个数据成员的值(因为它无法知道在哪里数组结束)。在C#中情况不同,因为数组是那里的对象,很像std::vector s,所以它们的大小是已知的。

Offtopic(对不起):

我想评论你的第二个原生C ++ BasicReader::ReadData方法实现,因为它会伤害我的C ++感觉;)你试图用C ++ 11风格编写C代码。 “有一种方法可以给猫皮肤”,但有一些建议:

  • 不要使用原始指针(char *),而是使用STL容器(std::vectorstd::string
  • 您是否有充分的理由使用std::unique_ptr<uint8_t[]> data + size_t dataSize std::vector<uint8_t>的{​​{1}}?
  • 避免使用原始operator new(),使用STL容器,std::make_sharedstd::make_unique(如果有)
  • seekg() + tellg()文件大小计数可以在大文件的情况下报告错误的大小

这段代码看起来不是更清洁,更安全:

std::vector<uint8_t> ReadData(const std::string filename)
{
    std::vector<uint8_t> data;

    std::ifstream fs;
    fs.open(filename, std::ifstream::in | std::ifstream::binary);
    if (fs.good())
    {
        auto size = FileSize(filename);
            // TODO: check here if size is more than size_t
        data.resize(static_cast<size_t>(size));
        fs.seekg(0, std::ios::beg);
        fs.read(reinterpret_cast<char*>(&data[0]), size);
        fs.close();
    }
    return data;
}

使用更加清洁:

std::vector<uint8_t> vertexShaderData = ReadData("VertexShader.cso");
if(vertexShaderData.empty()) {  /* handle it*/ }
auto wannaKnowSize = vertexShaderData.size();

作为奖励,你有一个漂亮的调试器可视化。

安全FileSize()实施。如果你的STL实现了它,你可以使用std::tr2的boost :: filesystem。

#include <filesystem>
namespace filesystem = std::tr2::sys;
/* or namespace filesystem = boost::filesystem */

uintmax_t FileSize(std::string filename)
{
    filesystem::path p(filename);
    if (filesystem::exists(p) && filesystem::is_regular_file(p))
        return filesystem::file_size(p);
    return 0;
}

希望它有所帮助。