tried to fix bugs (partial success)

This commit is contained in:
Timerix 2025-04-18 22:31:32 +05:00
parent 04e4f63fd7
commit d5d28d4884
8 changed files with 46 additions and 30 deletions

2
.vscode/tasks.json vendored
View File

@ -10,7 +10,7 @@
"command": "bash", "command": "bash",
"args": [ "args": [
"-c", "-c",
"cbuild build_exec_dbg" "cbuild rebuild_dependencies=src-csharp build_exec_dbg"
], ],
"options": { "options": {
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"

View File

@ -1,9 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
DEP_WORKING_DIR='src-csharp' DEP_WORKING_DIR='src-csharp'
CS_CONFIGURATION='Release'
if [[ "$TASK" = *_dbg ]]; then if [[ "$TASK" = *_dbg ]]; then
DEP_BUILD_COMMAND='dotnet build src-csharp.sln -o bin -c Debug' CS_CONFIGURATION='Debug'
else
DEP_BUILD_COMMAND='dotnet build src-csharp.sln -o bin -c Release'
fi fi
DEP_BUILD_COMMAND=$"dotnet build src-csharp.sln -o bin -c $CS_CONFIGURATION"
DEP_CLEAN_COMMAND='rm -rf bin obj' DEP_CLEAN_COMMAND='rm -rf bin obj'
DEP_OTHER_OUT_FILES='bin/Ougge.dll' DEP_OTHER_OUT_FILES='bin/Ougge.dll'

View File

@ -26,23 +26,21 @@ public class GameObject
public Transform Transform { get; } public Transform Transform { get; }
public GameObject? Parent; public GameObject? Parent;
public readonly Dictionary<Type, Component> Components = new(); public Dictionary<Type, Component> Components = new();
private GameObject() private GameObject(ulong id, uint nativePoolIndex)
{
}
private void Init(ulong id, uint nativePoolIndex)
{ {
_id = id; _id = id;
_index = nativePoolIndex; _index = nativePoolIndex;
// constructor doesn't work without writing to console
// TODO: FIX THIS BULLSHIT
Console.WriteLine($"GameObject(id: {id}, nativePoolIndex: {nativePoolIndex})");
} }
static public GameObject Create() static public GameObject Create()
{ {
NativeMethods.createGameObject(out ulong id, out uint index); NativeMethods.createGameObject(out ulong id, out uint index);
var o = new GameObject(); var o = new GameObject(id, index);
o.Init(id, index);
return o; return o;
} }
@ -56,6 +54,9 @@ public class GameObject
throw new Exception($"Can't destroy GameObject({_id})"); throw new Exception($"Can't destroy GameObject({_id})");
} }
/// <param name="t">type derived from Component</param>
/// <returns>true if new component instance was created, false if component of the same tipe is already added to GameObject</returns>
/// <exception cref="Exception"></exception>
public bool TryCreateComponent(Type t) public bool TryCreateComponent(Type t)
{ {
if(!t.IsSubclassOf(typeof(Component))) if(!t.IsSubclassOf(typeof(Component)))
@ -67,12 +68,13 @@ public class GameObject
Components.Add(t, (Component)Activator.CreateInstance(t, this)); Components.Add(t, (Component)Activator.CreateInstance(t, this));
return true; return true;
} }
private bool TryCreateComponent(string fullName) private bool TryCreateComponent_internal(string fullName)
{ {
return TryCreateComponent(Type.GetType(fullName)); Type t = Type.GetType(fullName) ?? throw new Exception($"type not found '{fullName}'");
return TryCreateComponent(t);
} }
private void UpdateComponents(double deltaTime) private void InvokeUpdate(double deltaTime)
{ {
foreach(var p in Components) foreach(var p in Components)
{ {

View File

@ -1,11 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net48</TargetFramework> <TargetFramework>net48</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<RootNamespace>Ougge</RootNamespace> <RootNamespace>Ougge</RootNamespace>
<ImplicitUsings>disable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -38,20 +38,28 @@ MonoMethod* tryGetMonoMethod(MonoClass* target_class, const std::string& name,
{ {
if(target_class == nullptr) if(target_class == nullptr)
throw UsefulException("target_class is nullptr"); throw UsefulException("target_class is nullptr");
// iterate each method // iterate each method
void* iter = nullptr; void* iter = nullptr;
MonoMethod* m = nullptr; MonoMethod* m = nullptr;
MonoType* return_type = nullptr;
std::vector<MonoType*> argument_types; std::vector<MonoType*> argument_types;
while( (m = mono_class_get_methods(target_class, &iter)) ){ while( (m = mono_class_get_methods(target_class, &iter)) ){
// compare name
std::string m_name = mono_method_get_name(m);
if(m_name != name)
continue;
argument_types.clear(); argument_types.clear();
MonoType* return_type = nullptr;
getMethodSignatureTypes(m, &return_type, argument_types); getMethodSignatureTypes(m, &return_type, argument_types);
// compare argument count // compare argument count
if(argument_types.size() != arg_classes_size) if(argument_types.size() != arg_classes_size)
continue; continue;
// compare return type // compare return type
if(!mono_metadata_type_equal(return_type, mono_class_get_type(return_class))) if(!mono_metadata_type_equal(return_type, mono_class_get_type(return_class)))
continue; continue;
// compare argument types // compare argument types
bool argument_types_mismatch = false; bool argument_types_mismatch = false;
for(size_t i = 0; i < arg_classes_size; i++){ for(size_t i = 0; i < arg_classes_size; i++){
@ -62,6 +70,7 @@ MonoMethod* tryGetMonoMethod(MonoClass* target_class, const std::string& name,
} }
if(argument_types_mismatch) if(argument_types_mismatch)
continue; continue;
// passed all tests successfully // passed all tests successfully
break; break;
} }

View File

@ -85,8 +85,11 @@ public:
void* arg_array[] = { valueToVoidPtr(args)..., nullptr }; void* arg_array[] = { valueToVoidPtr(args)..., nullptr };
MonoObject* ex = nullptr; MonoObject* ex = nullptr;
mono_runtime_invoke(method_ptr, class_instance, arg_array, &ex); mono_runtime_invoke(method_ptr, class_instance, arg_array, &ex);
if(ex) if(ex){
//TODO: call mono_trace_set_printerr_handler from mono/mono/utils/mono-logger.h
mono_print_unhandled_exception(ex); mono_print_unhandled_exception(ex);
throw UsefulException("Some C# exception occured");
}
}; };
/// all types must implement getClass<T>() /// all types must implement getClass<T>()
@ -94,9 +97,10 @@ public:
static MonoClass* arg_classes[] { getClass<ArgTypes>()... }; static MonoClass* arg_classes[] { getClass<ArgTypes>()... };
static MonoClass* return_class { getClass<ReturnT>() }; static MonoClass* return_class { getClass<ReturnT>() };
method_ptr = tryGetMonoMethod(target_class, name, return_class, arg_classes, sizeof...(ArgTypes)); method_ptr = tryGetMonoMethod(target_class, name, return_class, arg_classes, sizeof...(ArgTypes));
if(method_ptr == nullptr) if(method_ptr == nullptr){
throw UsefulException(format("can't get method '%s' from class '%s'", throw UsefulException(format("can't get method '%s' from class '%s'",
name.c_str(), mono_class_get_name(target_class))); name.c_str(), mono_class_get_name(target_class)));
}
} }
}; };

View File

@ -15,7 +15,8 @@ RuntimeJIT::RuntimeJIT(const std::string& domain_name){
} }
RuntimeJIT::~RuntimeJIT(){ RuntimeJIT::~RuntimeJIT(){
mono_jit_cleanup(domain); // TODO: fix segfault on cleanup
// mono_jit_cleanup(domain);
} }
std::shared_ptr<Assembly> RuntimeJIT::loadAssembly(const std::string &name){ std::shared_ptr<Assembly> RuntimeJIT::loadAssembly(const std::string &name){

View File

@ -46,22 +46,23 @@ int main(int argc, const char** argv){
MonoObject* exampleObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass); MonoObject* exampleObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass);
u64 obj_id = 0; u64 obj_id = 0;
auto pair = p.emplace(GameObject(exampleObjectManaged, nullptr)); auto pair = p.emplace(GameObject(exampleObjectManaged, nullptr));
mono_runtime_object_init(exampleObjectManaged); auto gameObjectCtor = Mono::Method<void(u64, u32)>(gameObjectClass, ".ctor");
auto exampleObjectInit = Mono::Method<void(u64, u32)>(gameObjectClass, "Init"); gameObjectCtor(exampleObjectManaged, obj_id++, pair.first);
exampleObjectInit(exampleObjectManaged, obj_id++, pair.first);
auto exampleObjectUpdate = Mono::Method<void(f64)>(gameObjectClass, "UpdateComponents");
auto exampleObjectUpdate = Mono::Method<void(f64)>(gameObjectClass, "InvokeUpdate");
updateCallbacks.push_back([exampleObjectManaged, exampleObjectUpdate](f64 deltaTime) -> void { updateCallbacks.push_back([exampleObjectManaged, exampleObjectUpdate](f64 deltaTime) -> void {
exampleObjectUpdate(exampleObjectManaged, deltaTime); exampleObjectUpdate(exampleObjectManaged, deltaTime);
}); });
auto tryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent"); auto tryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent_internal");
Mono::String componentNameManaged = mono_string_new(mono.getDomain(), "ExampleComponent"); Mono::String componentNameManaged = mono_string_new(mono.getDomain(), "Ougge.ExampleComponent");
Mono::ObjectHandle componentNameObjectHandle((MonoObject*)(void*)componentNameManaged); // Mono::ObjectHandle componentNameObjectHandle((MonoObject*)(void*)componentNameManaged);
Mono::Bool created = tryCreateComponent(exampleObjectManaged, componentNameManaged); Mono::Bool created = tryCreateComponent(exampleObjectManaged, componentNameManaged);
if(!created.wide_bool) if(!created.wide_bool)
throw UsefulException("couldn't create ExampleComponent"); throw UsefulException("couldn't create ExampleComponent");
std::cout<<"OK!"<<std::endl;
return 0;
GUI::MainWindow w; GUI::MainWindow w;
w.open("ougge", update); w.open("ougge", update);
std::cout<<"created sdl window"<<std::endl; std::cout<<"created sdl window"<<std::endl;