io — c ++ чтение (.cso) скомпилированный шейдерный объект, возвращающий \ 0

Я пробовал два разных метода для чтения из этого файла cso. Какой шейдер Microsoft скомпилирован

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
Тем не мение; когда я указываю на другой файл в том же каталоге, он дает мне данные. Что здесь происходит?
Вот файл.

Я прочитал первые несколько байтов файла, и это так:

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

0

Решение

Ваш код работает должным образом: char* data массив содержит данные файла. Что здесь происходит не так, что ваш char* data ваши визуализаторы неправильно интерпретируют массив (все, что вы используете для визуализации: визуализатор отладчика, std::cout, так далее). Все они пытаются напечатать строку с нулевым символом в конце (в стиле c), но она заканчивается мгновенно, так как первый символ равен 0. Необработанные массивы также можно визуализировать в отладчиках как указатели: адрес и только значение первого члена данных (потому что он не может знать, где массив заканчивается). В C # ситуация другая, так как массивы — это объекты, очень похожие на std::vectorс, так что их размер известен.

Оффтоп (извините за это):

Я хотел бы прокомментировать ваш второй, родной C ++ BasicReader::ReadData Реализация метода, как это больно мои чувства C ++;) Вы пытаетесь написать код C в стиле C ++ 11. «Существует более одного способа снять шкуру с кошки», но есть несколько советов:

  • не используйте сырые указатели (char *), вместо этого используйте контейнеры STL (std::vector, std::string)
  • у вас действительно хорошая причина использовать std::unique_ptr<uint8_t[]> data + size_t dataSize вместо std::vector<uint8_t>?
  • избегать использования сырья operator new(), используйте контейнеры STL, std::make_shared, std::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() реализация. Вы можете использовать любой boost :: filesystem, из std::tr2 если ваш STL реализовал это.

#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;
}

Надеюсь, это поможет как-то.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]