ralfbiedert / interoptopus

The polyglot bindings generator for your library (C#, C, Python, …) 🐙
302 stars 27 forks source link

SliceMutu32 does not contain a constructor that takes 1 arguments #73

Closed slasktotten closed 1 year ago

slasktotten commented 1 year ago

I am using Interoptopus to generate C# bindings for Unity. This is my Generator:

    Generator::new(config, rust_lib::my_inventory())
        //.add_overload_writer(DotNet::new())
        .add_overload_writer(Unity::new())
        .write_file("bindings/csharp/Interop.cs")?;

I am trying to pass a mutable slice from C# to Rust and write into it like so:

#[ffi_function]
#[no_mangle]
pub extern "C" fn mutate_slice_u32(slice: &mut FFISliceMut<u32>) {
    let data = vec![1, 2, 3, 4, 5];
    for (idx, el) in data.iter().enumerate() {
        slice[idx] = *el;
    }
}

The relevant generated binding looks like this:

        [DllImport(NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "mutate_slice_u32")]
        public static extern void mutate_slice_u32(ref SliceMutu32 slice);

        #if UNITY_2018_1_OR_NEWER
        public static void mutate_slice_u32(NativeArray<uint> slice)
        {
            var slice_slice = new SliceMutu32(slice);
            mutate_slice_u32(ref slice_slice);;
        }
        #endif

Issue is I am getting an error in Unity saying: Assets/Plugins/Interop.cs(53,35): error CS1729: 'SliceMutu32' does not contain a constructor that takes 1 arguments

Am I doing anything especially crazy here?

ralfbiedert commented 1 year ago

Can you change your signature to take the slice by value, like so

pub extern "C" fn mutate_slice_u32(slice: FFISliceMut<u32>) ...

and see if that helps?

slasktotten commented 1 year ago

Thanks for the quick reply! Unfortunately that didn't change anything. It also seems like the generated C# binding file is missing using Unity.Collections; Required by: NativeArray<uint>

ralfbiedert commented 1 year ago

Hm, unfortunately I can't reproduce this.

In the example Unity project it does create a "constructor that takes 1 arguments" like so:

        #if UNITY_2018_1_OR_NEWER
        public SliceMutu32(NativeArray<uint> handle)
        {
            unsafe
            {
                this.data = new IntPtr(NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr(handle));
                this.len = (ulong) handle.Length;
            }
        }
        #endif

The import is also present:

#if UNITY_2018_1_OR_NEWER
using Unity.Collections.LowLevel.Unsafe;
using Unity.Collections;
#endif

I would recommend to double-check the file backend_csharp_ui.rs to see how the Unity bindings are created there. It's a bit convoluted, but follow bindings_match_reference(), then the call to generate_bindings_multi("tests/output_unity/Assets").

If that doesn't help please post a minimal reproducible example, preferably as a Git repo somewhere.

slasktotten commented 1 year ago

Thanks I'll dig into it more. I am probably doing something silly :)

slasktotten commented 1 year ago

Still can't seem to make it work I'm afraid. I uploaded a minimal reproducible example. repro-example

ralfbiedert commented 1 year ago

There was a bug when these items were emitted, it only happened on Unsafe::UnsafePlatformMemCpy; 0.14.15 should fix that.