diff --git a/ScenariumEditor.NET/CoreInterop/CoreNative.cs b/ScenariumEditor.NET/CoreInterop/CoreNative.cs index e12de86..4a6f756 100644 --- a/ScenariumEditor.NET/CoreInterop/CoreNative.cs +++ b/ScenariumEditor.NET/CoreInterop/CoreNative.cs @@ -41,6 +41,46 @@ public List ToList() { return this.ToArray().ToList(); } + public T[] ToArray() where T : unmanaged { + var type = typeof(T); + + if (!type.IsPrimitive) { + if (type.IsValueType) { + if (!type.IsLayoutSequential && !type.IsExplicitLayout) { + throw new InvalidOperationException(string.Format("{0} does not define a StructLayout attribute", + type)); + } + } else { + throw new InvalidOperationException(string.Format("{0} is not a primitive or value type", type)); + } + } + + var tSize = Marshal.SizeOf(); + if (this.length % tSize != 0) throw new InvalidOperationException("Invalid array size"); + + var tLength = (int)this.length / tSize; + var result = new T[tLength]; + + if (tLength == 0) return result; + + GCHandle handle = new GCHandle(); + try { + // Make sure the array won't be moved around by the GC + handle = GCHandle.Alloc(result, GCHandleType.Pinned); + var destination = handle.AddrOfPinnedObject().ToPointer(); + Buffer.MemoryCopy(bytes, destination, length, length); + } finally { + if (handle.IsAllocated) + handle.Free(); + } + + return result; + } + + public List ToList() where T : unmanaged { + return this.ToArray().ToList(); + } + public void Dispose() { if (bytes != null) { Marshal.FreeHGlobal((IntPtr)bytes); @@ -50,14 +90,6 @@ public void Dispose() { } internal static unsafe partial class CoreNative { - public static void Test() { - var buf = test3(); - var result = buf.ToString(); - buf.Dispose(); - Console.WriteLine(result); - } - - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr LoadLibrary(string libname); diff --git a/ScenariumEditor.NET/CoreInterop/CoreNative.g.cs b/ScenariumEditor.NET/CoreInterop/CoreNative.g.cs index 94e0722..715098c 100644 --- a/ScenariumEditor.NET/CoreInterop/CoreNative.g.cs +++ b/ScenariumEditor.NET/CoreInterop/CoreNative.g.cs @@ -16,14 +16,8 @@ internal static unsafe partial class CoreNative - [DllImport(__DllName, EntryPoint = "test3", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern FfiBuf test3(); - - [DllImport(__DllName, EntryPoint = "add", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern uint add(uint left, uint right); - - [DllImport(__DllName, EntryPoint = "test1", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern void test1(); + [DllImport(__DllName, EntryPoint = "dummy", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void dummy(FfiBuf _a); } diff --git a/ScenariumEditor.NET/CoreInterop/ScenariumCore.cs b/ScenariumEditor.NET/CoreInterop/ScenariumCore.cs index 53679ea..366688a 100644 --- a/ScenariumEditor.NET/CoreInterop/ScenariumCore.cs +++ b/ScenariumEditor.NET/CoreInterop/ScenariumCore.cs @@ -17,11 +17,5 @@ public ScenariumCore() { } } - - public String Test() { - var buf = CoreNative.test3(); - var result = buf.ToString(); - // buf.Dispose(); - return result; - } + } \ No newline at end of file diff --git a/ScenariumEditor.NET/ScenariumEditor.NET/MainWindow.xaml.cs b/ScenariumEditor.NET/ScenariumEditor.NET/MainWindow.xaml.cs index 9df25e4..3e79570 100644 --- a/ScenariumEditor.NET/ScenariumEditor.NET/MainWindow.xaml.cs +++ b/ScenariumEditor.NET/ScenariumEditor.NET/MainWindow.xaml.cs @@ -35,9 +35,6 @@ public MainWindow() { private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) { ScenariumCore.Init(); - - var result = new ScenariumCore().Test(); - MessageBox.Show(result); } private void MainWindow_OnUnloaded(object sender, RoutedEventArgs e) { diff --git a/cs_interop/build.rs b/cs_interop/build.rs index 8a8657d..763e519 100644 --- a/cs_interop/build.rs +++ b/cs_interop/build.rs @@ -4,6 +4,7 @@ fn main() { .csharp_dll_name("core_interop") .csharp_class_name("CoreNative") .csharp_namespace("CoreInterop") + .csharp_class_accessibility("internal") .generate_csharp_file("../ScenariumEditor.NET/CoreInterop/CoreNative.g.cs") .unwrap(); diff --git a/cs_interop/src/lib.rs b/cs_interop/src/lib.rs index 643dbeb..0f41c56 100644 --- a/cs_interop/src/lib.rs +++ b/cs_interop/src/lib.rs @@ -1,38 +1,40 @@ +#![allow(dead_code)] +#![deny(improper_ctypes_definitions)] + use std::mem::forget; use std::string::FromUtf8Error; -use graph::graph::Graph; -use imaginarium::color_format::ColorFormat; -use imaginarium::image::{Image, ImageDesc}; - #[repr(C)] -pub struct FfiBuf { +struct FfiBuf { bytes: *mut u8, length: u32, capacity: u32, } #[no_mangle] -pub extern "C" fn test3() -> FfiBuf { - "Hello from Rust!".into() -} - -#[no_mangle] -pub extern "C" fn add(left: u32, right: u32) -> u32 { - left + right -} - -#[no_mangle] -pub extern "C" fn test1() { - let _img = Image::new_empty(ImageDesc::new(10, 10, ColorFormat::RGB_U8)); - let _graph = Graph::default(); -} +extern "C" fn dummy(_a: FfiBuf) {} impl FfiBuf { pub fn as_slice(&self) -> &[u8] { unsafe { std::slice::from_raw_parts(self.bytes, self.length as usize) } } } +impl From<[T; N]> for FfiBuf +where + T: Clone, +{ + fn from(data: [T; N]) -> Self { + data.to_vec().into() + } +} +impl From<&[T]> for FfiBuf +where + T: Clone, +{ + fn from(data: &[T]) -> Self { + data.to_vec().into() + } +} impl From<&str> for FfiBuf { fn from(data: &str) -> Self { data.to_string().into() @@ -61,16 +63,17 @@ impl From for Vec { unsafe { Vec::from_raw_parts(ptr, len, cap) } } } -impl From> for FfiBuf { - fn from(mut data: Vec) -> Self { - let len = data.len(); - let cap = data.capacity(); +impl From> for FfiBuf { + fn from(mut data: Vec) -> Self { + let t_size = std::mem::size_of::(); + let len = data.len() * t_size; + let cap = data.capacity() * t_size; let ptr = data.as_mut_ptr(); forget(data); FfiBuf { - bytes: ptr, + bytes: ptr as *mut u8, length: len as u32, capacity: cap as u32, }