重新封装二进制文件读取

This commit is contained in:
2025-10-27 12:35:51 +08:00
parent c5a88ac5e3
commit 9e0a2963e8
6 changed files with 246 additions and 68 deletions

View File

@ -0,0 +1,103 @@
//
// Created by sfd on 25-10-26.
//
#ifndef BUFFER_H
#define BUFFER_H
#include <cstdint>
namespace Hazel
{
struct Buffer
{
uint8_t* Data = nullptr;
uint64_t Size = 0;
Buffer() = default;
Buffer(const uint64_t size)
{
Allocate(size);
}
Buffer(const Buffer&) = default;
static Buffer Copy(const Buffer other)
{
const Buffer result(other.Size);
memcpy(result.Data, other.Data, other.Size);
return result;
}
void Allocate(uint64_t size)
{
Release();
Data = new uint8_t[size];
Size = size;
}
void Release()
{
if (Data != nullptr)
delete[] Data;
Data = nullptr;
Size = 0;
}
template<typename T>
T* As()
{
return reinterpret_cast<T*>(Data);
}
explicit operator bool() const
{
return static_cast<bool>(Data);
}
};
struct ScopedBuffer
{
ScopedBuffer(Buffer buffer)
: m_Buffer(buffer)
{
}
ScopedBuffer(uint64_t size)
: m_Buffer(size)
{
}
~ScopedBuffer()
{
m_Buffer.Release();
}
uint8_t* Data() const
{
return m_Buffer.Data;
}
uint64_t Size() const
{
return m_Buffer.Size;
}
template<typename T>
T* As()
{
return m_Buffer.As<T>();
}
explicit operator bool() const
{
return static_cast<bool>(m_Buffer);
}
private:
Buffer m_Buffer;
};
}
#endif //BUFFER_H

View File

@ -0,0 +1,39 @@
//
// Created by sfd on 25-10-26.
//
#include "FileSystem.h"
#include <fstream>
#include "Log.h"
namespace Hazel
{
Buffer FileSystem::ReadFileBinary(const std::filesystem::path& filePath)
{
std::ifstream file(filePath, std::ios::binary | std::ios::ate);
if (!file)
{
HZ_CORE_WARN("could not open file '{0}'", filePath.string());
return {};
}
std::streampos end = file.tellg();
file.seekg(0, std::ios::beg);
uint64_t size = end - file.tellg();
if (size == 0)
{
HZ_CORE_WARN("file is empty");
return {};
}
Buffer buffer(size);
file.read(buffer.As<char>(), size);
file.close();
return buffer;
}
}

View File

@ -0,0 +1,22 @@
//
// Created by sfd on 25-10-26.
//
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <filesystem>
#include "Buffer.h"
#include "Core.h"
namespace Hazel
{
class HAZEL_API FileSystem
{
public:
static Buffer ReadFileBinary(const std::filesystem::path& filePath);
};
}
#endif //FILESYSTEM_H

View File

@ -148,6 +148,18 @@ namespace YAML
namespace Hazel namespace Hazel
{ {
#define WRITE_FIELD_TYPE(FieldType, Type) \
case ScriptFieldType::FieldType: \
out << scriptField.GetValue<Type>();break
#define READ_FIELD_TYPE(FieldType, Type) \
case ScriptFieldType::FieldType: \
{ \
Type valueData = scriptField["Data"].as<Type>(); \
fieldInstance.SetValue(valueData); \
break; \
}
@ -252,9 +264,7 @@ namespace Hazel
out << YAML::Key << "Data" << YAML::Value; out << YAML::Key << "Data" << YAML::Value;
ScriptFieldInstance& scriptField = entityFields.at(name); ScriptFieldInstance& scriptField = entityFields.at(name);
#define WRITE_FIELD_TYPE(FieldType, Type) case ScriptFieldType::FieldType:\
out << scriptField.GetValue<Type>();\
break
switch (field.Type) switch (field.Type)
{ {
@ -279,7 +289,6 @@ namespace Hazel
} }
out << YAML::EndMap; out << YAML::EndMap;
#undef WRITE_FIELD_TYPE
} }
out << YAML::EndSeq; out << YAML::EndSeq;
@ -483,51 +492,44 @@ namespace Hazel
if (scriptFields) if (scriptFields)
{ {
Ref<ScriptClass> entityClass = ScriptEngine::GetEntityClass(sc.ClassName); Ref<ScriptClass> entityClass = ScriptEngine::GetEntityClass(sc.ClassName);
const auto& fields = entityClass->GetFields(); if (entityClass)
auto& entityFields = ScriptEngine::GetScriptFieldMap(deserializedEntity);
for (auto scriptField: scriptFields)
{ {
std::string name = scriptField["Name"].as<std::string>(); const auto& fields = entityClass->GetFields();
std::string typeName = scriptField["Type"].as<std::string>(); auto& entityFields = ScriptEngine::GetScriptFieldMap(deserializedEntity);
ScriptFieldType type = Utils::ScriptFieldTypeFromString(typeName);
ScriptFieldInstance& fieldInstance = entityFields[name];
fieldInstance.Field = fields.at(name); for (auto scriptField: scriptFields)
#define READ_FIELD_TYPE(FieldType, Type) \
case ScriptFieldType::FieldType: \
{ \
Type valueData = scriptField["Data"].as<Type>(); \
fieldInstance.SetValue(valueData); \
break; \
}
switch (type)
{ {
READ_FIELD_TYPE(Float, float); std::string name = scriptField["Name"].as<std::string>();
READ_FIELD_TYPE(Double, double); std::string typeName = scriptField["Type"].as<std::string>();
READ_FIELD_TYPE(Boolean, bool); ScriptFieldType type = Utils::ScriptFieldTypeFromString(typeName);
READ_FIELD_TYPE(Char, char); ScriptFieldInstance& fieldInstance = entityFields[name];
READ_FIELD_TYPE(Byte, int8_t);
READ_FIELD_TYPE(Short, int16_t);
READ_FIELD_TYPE(Int, int32_t);
READ_FIELD_TYPE(Long, int64_t);
READ_FIELD_TYPE(UByte, uint8_t);
READ_FIELD_TYPE(UShort, uint16_t);
READ_FIELD_TYPE(UInt, uint32_t);
READ_FIELD_TYPE(ULong, uint64_t);
READ_FIELD_TYPE(Vector2, glm::vec2); fieldInstance.Field = fields.at(name);
READ_FIELD_TYPE(Vector3, glm::vec3);
READ_FIELD_TYPE(Vector4, glm::vec4);
READ_FIELD_TYPE(Entity, UUID);
switch (type)
{
READ_FIELD_TYPE(Float, float);
READ_FIELD_TYPE(Double, double);
READ_FIELD_TYPE(Boolean, bool);
READ_FIELD_TYPE(Char, char);
READ_FIELD_TYPE(Byte, int8_t);
READ_FIELD_TYPE(Short, int16_t);
READ_FIELD_TYPE(Int, int32_t);
READ_FIELD_TYPE(Long, int64_t);
READ_FIELD_TYPE(UByte, uint8_t);
READ_FIELD_TYPE(UShort, uint16_t);
READ_FIELD_TYPE(UInt, uint32_t);
READ_FIELD_TYPE(ULong, uint64_t);
READ_FIELD_TYPE(Vector2, glm::vec2);
READ_FIELD_TYPE(Vector3, glm::vec3);
READ_FIELD_TYPE(Vector4, glm::vec4);
READ_FIELD_TYPE(Entity, UUID);
}
} }
#undef READ_FIELD_TYPE
} }
} }
} }

View File

@ -10,6 +10,8 @@
#include "FileWatch.h" #include "FileWatch.h"
#include "ScriptGlue.h" #include "ScriptGlue.h"
#include "Hazel/Core/Application.h" #include "Hazel/Core/Application.h"
#include "Hazel/Core/Buffer.h"
#include "Hazel/Core/FileSystem.h"
#include "mono/jit/jit.h" #include "mono/jit/jit.h"
#include "mono/metadata/assembly.h" #include "mono/metadata/assembly.h"
#include "mono/metadata/attrdefs.h" #include "mono/metadata/attrdefs.h"
@ -46,6 +48,7 @@ namespace Hazel
namespace Utils namespace Utils
{ {
/*
char* ReadBytes(const std::filesystem::path& filePath, uint32_t* outSize) char* ReadBytes(const std::filesystem::path& filePath, uint32_t* outSize)
{ {
std::ifstream stream(filePath, std::ios::binary | std::ios::ate); std::ifstream stream(filePath, std::ios::binary | std::ios::ate);
@ -73,16 +76,15 @@ namespace Hazel
*outSize = (uint32_t)size; *outSize = (uint32_t)size;
return buffer; return buffer;
} }
*/
MonoAssembly* LoadMonoAssembly(const std::filesystem::path& assemblyPath, bool loadPDB = false) MonoAssembly* LoadMonoAssembly(const std::filesystem::path& assemblyPath, bool loadPDB = false)
{ {
HZ_CORE_DEBUG("Load Assemble: {0}", assemblyPath.string().c_str()); HZ_CORE_DEBUG("Load Assemble: {0}", assemblyPath.string().c_str());
uint32_t fileSize = 0; ScopedBuffer fileData = FileSystem::ReadFileBinary(assemblyPath);
char* fileData = ReadBytes(assemblyPath, &fileSize);
MonoImageOpenStatus status; MonoImageOpenStatus status;
MonoImage* image = mono_image_open_from_data_full(fileData, fileSize, 1, &status, 0); MonoImage* image = mono_image_open_from_data_full(fileData.As<char>(), fileData.Size(), 1, &status, 0);
if (status != MONO_IMAGE_OK) if (status != MONO_IMAGE_OK)
{ {
const char* errorMessage = mono_image_strerror(status); const char* errorMessage = mono_image_strerror(status);
@ -98,13 +100,10 @@ namespace Hazel
if (std::filesystem::exists(pdbPath)) if (std::filesystem::exists(pdbPath))
{ {
uint32_t pdbFileSize = 0; ScopedBuffer pdbFileData = FileSystem::ReadFileBinary(pdbPath);
char* pdbFileData = ReadBytes(pdbPath, &pdbFileSize); mono_debug_open_image_from_memory(image, pdbFileData.As<mono_byte>(), fileData.Size());
mono_debug_open_image_from_memory(image, (const mono_byte*)pdbFileData, fileSize);
HZ_CORE_INFO("loaded pdb file: {0}", pdbPath.string()); HZ_CORE_INFO("loaded pdb file: {0}", pdbPath.string());
HZ_CORE_INFO(" size: {0}", pdbFileSize); HZ_CORE_INFO(" size: {0}", pdbFileData.Size());
delete[] pdbFileData;
} }
} }
@ -112,8 +111,6 @@ namespace Hazel
MonoAssembly* assembly = mono_assembly_load_from_full(image, string.c_str(), &status, 0); MonoAssembly* assembly = mono_assembly_load_from_full(image, string.c_str(), &status, 0);
mono_image_close(image); mono_image_close(image);
delete[] fileData;
return assembly; return assembly;
} }
@ -200,8 +197,20 @@ namespace Hazel
InitMono(); InitMono();
ScriptGlue::RegisterFunctions(); ScriptGlue::RegisterFunctions();
LoadAssemble("Resources/Scripts/Hazel-ScriptCore.dll"); bool status = LoadAssemble("Resources/Scripts/Hazel-ScriptCore.dll");
LoadAppAssemble("Resources/Scripts/Sandbox.dll"); if (!status)
{
HZ_CORE_ERROR("[ScriptEngine] Could not load Hazel-ScriptCore assembly.");
return;
}
status = LoadAppAssemble("Resources/Scripts/Sandbox.dll");
if (!status)
{
HZ_CORE_ERROR("[ScriptEngine] Could not load app assembly.");
return;
}
LoadAssemblyClass(); LoadAssemblyClass();
Utils::PrintAssemblyTypes(s_Data->CoreAssembly); Utils::PrintAssemblyTypes(s_Data->CoreAssembly);
ScriptGlue::RegisterComponents(); ScriptGlue::RegisterComponents();
@ -249,32 +258,36 @@ namespace Hazel
delete s_Data; delete s_Data;
} }
void ScriptEngine::LoadAssemble(const std::filesystem::path& assemblePath) bool ScriptEngine::LoadAssemble(const std::filesystem::path& assemblePath)
{ {
// Create an Domain App // Create an Domain App
char monoDomainName[] = "HazelScriptRuntime"; char monoDomainName[] = "HazelScriptRuntime";
s_Data->AppDomain = mono_domain_create_appdomain(monoDomainName, nullptr); s_Data->AppDomain = mono_domain_create_appdomain(monoDomainName, nullptr);
mono_domain_set(s_Data->AppDomain, true); mono_domain_set(s_Data->AppDomain, true);
// TODO: move this later
s_Data->CoreAssemblyFilePath = assemblePath; s_Data->CoreAssemblyFilePath = assemblePath;
s_Data->CoreAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); s_Data->CoreAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging);
s_Data->CoreAssemblyImage = mono_assembly_get_image(s_Data->CoreAssembly); if (s_Data->CoreAssembly == nullptr)
return false;
// Utils::PrintAssemblyTypes(s_Data->CoreAssembly); s_Data->CoreAssemblyImage = mono_assembly_get_image(s_Data->CoreAssembly);
return true;
} }
void ScriptEngine::LoadAppAssemble(const std::filesystem::path& assemblePath) bool ScriptEngine::LoadAppAssemble(const std::filesystem::path& assemblePath)
{ {
// TODO: move this later // TODO: move this later
s_Data->AppAssemblyFilePath = assemblePath; s_Data->AppAssemblyFilePath = assemblePath;
s_Data->AppAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); s_Data->AppAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging);
if (s_Data->AppAssembly == nullptr)
return false;
s_Data->AppAssemblyImage = mono_assembly_get_image(s_Data->AppAssembly); s_Data->AppAssemblyImage = mono_assembly_get_image(s_Data->AppAssembly);
s_Data->AppAssemblyFileWatcher = CreateScope<filewatch::FileWatch<std::string>>(assemblePath.string(), OnAssemblyFileSystemEvent); s_Data->AppAssemblyFileWatcher = CreateScope<filewatch::FileWatch<std::string>>(assemblePath.string(), OnAssemblyFileSystemEvent);
auto& b = s_Data;
s_Data->AssemblyReloading = false; s_Data->AssemblyReloading = false;
// Utils::PrintAssemblyTypes(s_Data->CoreAssembly);
return true;
} }
void ScriptEngine::ReloadAssemble() void ScriptEngine::ReloadAssemble()
@ -402,8 +415,7 @@ namespace Hazel
UUID entityUUID = entity.GetUUID(); UUID entityUUID = entity.GetUUID();
if (!s_Data->EntityInstances.contains(entityUUID)) if (!s_Data->EntityInstances.contains(entityUUID))
{ {
HZ_CORE_FATAL("script cannot get"); HZ_CORE_ERROR("Could not find ScriptInstance for entity {}", (uint64_t)entityUUID);
assert(1);
} }
const Ref<ScriptInstance> instance = s_Data->EntityInstances[entityUUID]; const Ref<ScriptInstance> instance = s_Data->EntityInstances[entityUUID];

View File

@ -145,8 +145,8 @@ namespace Hazel
static void Init(); static void Init();
static void Shutdown(); static void Shutdown();
static void LoadAssemble(const std::filesystem::path& assemblePath); static bool LoadAssemble(const std::filesystem::path& assemblePath);
static void LoadAppAssemble(const std::filesystem::path& assemblePath); static bool LoadAppAssemble(const std::filesystem::path& assemblePath);
static void ReloadAssemble(); static void ReloadAssemble();