Biohazrd icon indicating copy to clipboard operation
Biohazrd copied to clipboard

Improve friendliness of constructing/destructing C++ objects

Open PathogenDavid opened this issue 3 years ago • 1 comments

Right now Biohazrd emits constructors and destructors as normal instance methods, they both act as if they would for placement new.

This leads to somewhat clunky usage for allocating objects from C#. For example:

struct MyStruct
{
public:
    float x;
    float y;
    MyClass(float x, float y);
    ~MyClass();
};

Will generate something like:

[StructLayout(LayoutKind.Explicit, Size = 8)]
public unsafe partial struct MyStruct
{
    [FieldOffset(0)] public float x;
    [FieldOffset(4)] public float y;

    [DllImport("Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "__InlineHelper0", ExactSpelling = true)]
    private static extern void Constructor_PInvoke(MyStruct* @this, float x, float y);

    [DebuggerStepThrough, DebuggerHidden]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public unsafe void Constructor(float x, float y)
    {
        fixed (ImVec2* @this = &this)
        { Constructor_PInvoke(@this, x, y); }
    }

    [DllImport("InfectedImGui.Native.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "__InlineHelper1", ExactSpelling = true)]
    private static extern void Destructor_PInvoke(MyStruct* @this);

    [DebuggerStepThrough, DebuggerHidden]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public unsafe void Destructor()
    {
        fixed (MyStruct* @this = &this)
        { Destructor_PInvoke(@this); }
    }
}

"Proper" usage of this type in a stack-allocated context looks like this:

MyStruct myStruct = default;
myStruct.Constructor(100f, 200f);
Console.WriteLine($"myStruct = {myStruct.x}, {myStruct.y}");
myStruct.Destructor();

Ideally we'd like it to be able to look like this:

using (MyStruct myStruct = new(100f, 200f))
{ Console.WriteLine($"myStruct = {myStruct.x}, {myStruct.y}"); }

Other things we should ideally support:

  • Placement new (IE: from a heap allocated in C#)
  • Deletion (https://github.com/InfectedLibraries/Biohazrd/issues/159)

Other things to ponder:

  • Should constructors be exposed as static methods instead? (Would allow placement new more naturally, struct constructors would be wrappers of it.)

PathogenDavid avatar Feb 21 '21 10:02 PathogenDavid

It's somehow not mentioned above, but parameterless constructors are coming to C# 10 so that solves the main reason I hadn't actually done this yet. Julien Couvreur confirmed they should land in 2022p3: https://github.com/dotnet/roslyn/pull/54359#issuecomment-868837007

PathogenDavid avatar Jul 04 '21 13:07 PathogenDavid