-
Notifications
You must be signed in to change notification settings - Fork 353
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
.NET: Implement API wrappers on the C++/CLI side
- Loading branch information
Showing
18 changed files
with
874 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#pragma once | ||
|
||
#include <reframework/API.hpp> | ||
|
||
#pragma managed | ||
|
||
namespace REFrameworkNET { | ||
ref class TypeDefinition; | ||
|
||
public ref class Field { | ||
public: | ||
Field(const reframework::API::Field* field) : m_field(field) {} | ||
|
||
System::String^ GetName() { | ||
return gcnew System::String(m_field->get_name()); | ||
} | ||
|
||
TypeDefinition^ GetDeclaringType() { | ||
auto t = m_field->get_declaring_type(); | ||
|
||
if (t == nullptr) { | ||
return nullptr; | ||
} | ||
|
||
return gcnew TypeDefinition(t); | ||
} | ||
|
||
TypeDefinition^ GetType() { | ||
auto t = m_field->get_type(); | ||
|
||
if (t == nullptr) { | ||
return nullptr; | ||
} | ||
|
||
return gcnew TypeDefinition(t); | ||
} | ||
|
||
uint32_t GetOffsetFromBase() { | ||
return m_field->get_offset_from_base(); | ||
} | ||
|
||
uint32_t GetOffsetFromFieldPtr() { | ||
return m_field->get_offset_from_fieldptr(); | ||
} | ||
|
||
uint32_t GetFlags() { | ||
return m_field->get_flags(); | ||
} | ||
|
||
bool IsStatic() { | ||
return m_field->is_static(); | ||
} | ||
|
||
bool IsLiteral() { | ||
return m_field->is_literal(); | ||
} | ||
|
||
uintptr_t GetInitDataPtr() { | ||
return (uintptr_t)m_field->get_init_data(); | ||
} | ||
|
||
uintptr_t GetDataRaw(uintptr_t obj, bool isValueType) { | ||
return (uintptr_t)m_field->get_data_raw((void*)obj, isValueType); | ||
} | ||
|
||
// I have no idea if this will work correctly | ||
template<typename T> | ||
T GetData(uintptr_t obj, bool isValueType) { | ||
return m_field->get_data<T>((void*)obj, isValueType); | ||
} | ||
|
||
private: | ||
const reframework::API::Field* m_field; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#pragma once | ||
|
||
#include <reframework/API.hpp> | ||
|
||
#pragma managed | ||
|
||
namespace REFrameworkNET { | ||
public ref struct InvokeRet { | ||
InvokeRet(const reframework::InvokeRet& ret) { | ||
Bytes = gcnew array<uint8_t>(ret.bytes.size()); | ||
for (size_t i = 0; i < ret.bytes.size(); i++) { | ||
Bytes[i] = ret.bytes[i]; | ||
} | ||
Byte = ret.byte; | ||
Word = ret.word; | ||
DWord = ret.dword; | ||
F = ret.f; | ||
QWord = ret.qword; | ||
D = ret.d; | ||
Ptr = gcnew System::UIntPtr(ret.ptr); | ||
ExceptionThrown = ret.exception_thrown; | ||
} | ||
|
||
// TODO: improve this? Does .NET have unions? | ||
property array<uint8_t>^ Bytes; | ||
property uint8_t Byte; | ||
property uint16_t Word; | ||
property uint32_t DWord; | ||
property float F; | ||
property uint64_t QWord; | ||
property double D; | ||
property System::Object^ Ptr; | ||
property bool ExceptionThrown; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "TypeDefinition.hpp" | ||
|
||
#include "ManagedObject.hpp" | ||
|
||
namespace REFrameworkNET { | ||
TypeDefinition^ ManagedObject::GetTypeDefinition() { | ||
auto result = m_object->get_type_definition(); | ||
|
||
if (result == nullptr) { | ||
return nullptr; | ||
} | ||
|
||
return gcnew TypeDefinition(result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#pragma once | ||
|
||
#include <reframework/API.hpp> | ||
|
||
#pragma managed | ||
|
||
namespace REFrameworkNET { | ||
ref class TypeDefinition; | ||
|
||
public ref class ManagedObject { | ||
public: | ||
ManagedObject(reframework::API::ManagedObject* obj) : m_object(obj) { | ||
AddRef(); | ||
} | ||
ManagedObject(::REFrameworkManagedObjectHandle handle) : m_object(reinterpret_cast<reframework::API::ManagedObject*>(handle)) { | ||
AddRef(); | ||
} | ||
|
||
~ManagedObject() { | ||
if (m_object != nullptr) { | ||
Release(); | ||
} | ||
} | ||
|
||
void AddRef() { | ||
m_object->add_ref(); | ||
} | ||
|
||
void Release() { | ||
m_object->release(); | ||
} | ||
|
||
void* Ptr() { | ||
return (void*)m_object; | ||
} | ||
|
||
uintptr_t GetAddress() { | ||
return (uintptr_t)m_object; | ||
} | ||
|
||
TypeDefinition^ GetTypeDefinition(); | ||
|
||
private: | ||
reframework::API::ManagedObject* m_object; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#pragma once | ||
|
||
#include <reframework/API.hpp> | ||
|
||
#pragma managed | ||
|
||
namespace REFrameworkNET { | ||
ref class ManagedObject; | ||
ref class TypeDefinition; | ||
ref class TypeInfo; | ||
|
||
public ref struct ManagedSingleton { | ||
ManagedSingleton(ManagedObject^ instance, TypeDefinition^ type, TypeInfo^ typeInfo) | ||
{ | ||
Instance = instance; | ||
Type = type; | ||
TypeInfo = typeInfo; | ||
} | ||
|
||
property ManagedObject^ Instance; | ||
property TypeDefinition^ Type; | ||
property TypeInfo^ TypeInfo; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#include "ManagedObject.hpp" | ||
|
||
#include "Method.hpp" | ||
|
||
namespace REFrameworkNET { | ||
REFrameworkNET::InvokeRet^ Method::Invoke(System::Object^ obj, array<System::Object^>^ args) { | ||
// We need to convert the managed objects to 8 byte representations | ||
std::vector<void*> args2{}; | ||
args2.resize(args->Length); | ||
|
||
for (int i = 0; i < args->Length; ++i) { | ||
//args2[i] = args[i]->ptr(); | ||
const auto t = args[i]->GetType(); | ||
|
||
if (t == System::Byte::typeid) { | ||
uint8_t v = System::Convert::ToByte(args[i]); | ||
args2[i] = (void*)(uint64_t)v; | ||
} else if (t == System::UInt16::typeid) { | ||
uint16_t v = System::Convert::ToUInt16(args[i]); | ||
args2[i] = (void*)(uint64_t)v; | ||
} else if (t == System::UInt32::typeid) { | ||
uint32_t v = System::Convert::ToUInt32(args[i]); | ||
args2[i] = (void*)(uint64_t)v; | ||
} else if (t == System::Single::typeid) { | ||
float v = System::Convert::ToSingle(args[i]); | ||
args2[i] = (void*)(uint64_t)v; | ||
} else if (t == System::UInt64::typeid) { | ||
uint64_t v = System::Convert::ToUInt64(args[i]); | ||
args2[i] = (void*)(uint64_t)v; | ||
} else if (t == System::Double::typeid) { | ||
double v = System::Convert::ToDouble(args[i]); | ||
args2[i] = (void*)(uint64_t)v; | ||
} else if (t == System::IntPtr::typeid) { | ||
args2[i] = (void*)(uint64_t)System::Convert::ToInt64(args[i]); | ||
} else { | ||
//args2[i] = args[i]->ptr(); | ||
} | ||
} | ||
|
||
void* obj_ptr = nullptr; | ||
|
||
if (obj != nullptr) { | ||
const auto obj_t = obj->GetType(); | ||
if (obj_t == System::IntPtr::typeid || obj_t == System::UIntPtr::typeid) { | ||
obj_ptr = (void*)(uint64_t)System::Convert::ToInt64(obj); | ||
} else if (obj_t == REFrameworkNET::ManagedObject::typeid) { | ||
obj_ptr = safe_cast<REFrameworkNET::ManagedObject^>(obj)->Ptr(); | ||
} else { | ||
//obj_ptr = obj->ptr(); | ||
} | ||
} | ||
|
||
const auto native_result = m_method->invoke((reframework::API::ManagedObject*)obj_ptr, args2); | ||
|
||
return gcnew REFrameworkNET::InvokeRet(native_result); | ||
} | ||
} |
Oops, something went wrong.