Can't find a way to generate a function that allocates memory

Open
#1,121 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
cpp, csharp
Domain
devtools, tooling

Research direction

Start from the generator path that handles CS_OUT parameters and the code that creates temporary result variables; the issue includes the C++ declaration, C# setup, and generated output to reproduce the problem. Done means pointer-to-pointer out parameters are marshalled correctly and generated local names remain unique so the output compiles.

Written by the indexing model from the issue text.

Description

bug
Brief Description

I couldn't find a way to setup the generator so it correctly generates a function that allocates the memory and returns it as an out parameter.

OS: Windows

Used headers
#define CS_OUT

typedef struct test_struct_t test_struct_t;

typedef struct test_pool_t test_pool_t;

void create_test_struct(CS_OUT test_struct_t** result, test_pool_t* pool);

The function create_test_struct allocates a new test_struct_t from the pool, and returns pointer to this struct to the caller -- so result is a pointer to a pointer.

Used settings

Target: MSVC (I think)

public void Setup(Driver driver)
{
    driver.Options.GeneratorKind = GeneratorKind.CSharp;
    var module = driver.Options.AddModule("TestModule");
    module.IncludeDirs.Add(Environment.CurrentDirectory);
    module.Headers.Add("TestHeader.h");
}

public void SetupPasses(Driver driver)
{
    driver.AddTranslationUnitPass(new CheckMacroPass());
}
Stack trace or incompilable generated code
public unsafe partial class TestHeader
{
    public partial struct __Internal
    {
        [SuppressUnmanagedCodeSecurity]
        [DllImport("TestModule", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
            EntryPoint="?create_test_struct@@YAXPEAPEAUtest_struct_t@@PEAUtest_pool_t@@@Z")]
        internal static extern void CreateTestStruct(global::System.IntPtr result, global::System.IntPtr pool);
    }

    public static void CreateTestStruct(out global::TestModule.TestStructT result, out global::TestModule.TestPoolT pool)
    {
        result = new global::TestModule.TestStructT();
        var __arg0 = ReferenceEquals(result, null) ? global::System.IntPtr.Zero : result.__Instance;
        pool = new global::TestModule.TestPoolT();
        var __arg1 = ReferenceEquals(pool, null) ? global::System.IntPtr.Zero : pool.__Instance;
        __Internal.CreateTestStruct(__arg0, __arg1);
        global::TestModule.TestStructT __result0;
        if (__arg0 == IntPtr.Zero) __result0 = null;
        else if (global::TestModule.TestStructT.NativeToManagedMap.ContainsKey(__arg0))
            __result0 = (global::TestModule.TestStructT) global::TestModule.TestStructT.NativeToManagedMap[__arg0];
        else __result0 = global::TestModule.TestStructT.__CreateInstance(__arg0);
        result = __result0;
        global::TestModule.TestPoolT __result0;
        if (__arg1 == IntPtr.Zero) __result0 = null;
        else if (global::TestModule.TestPoolT.NativeToManagedMap.ContainsKey(__arg1))
            __result0 = (global::TestModule.TestPoolT) global::TestModule.TestPoolT.NativeToManagedMap[__arg1];
        else __result0 = global::TestModule.TestPoolT.__CreateInstance(__arg1);
        pool = __result0;
    }
}

The problem with this code is that it doesn't treat the result parameter as a pointer to pointer, e.g. an out parameter of the native function. So it passes it to NativeToManagedMap and __CreateInstance as is instead of dereferencing it first.

This code is also incompilable because of this:

global::TestModule.TestStructT __result0;
if (__arg0 == IntPtr.Zero) __result0 = null;
...
result = __result0;
global::TestModule.TestPoolT __result0;
if (__arg1 == IntPtr.Zero) __result0 = null;
...
pool = __result0;

In this case, two variables with the same name __result0 are declared. This of course leads to a compilation error. The second variable should have been called __result1 here.

Dominant language
C#
Stars
3.4k
Forks
541
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from mono/CppSharp

All issues in mono/CppSharp

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.