Skip to content

Commit

Permalink
Update C# and Rust interop code
Browse files Browse the repository at this point in the history
This commit removes several test functions and optimizes the data transfer between languages. It adds better handling and conversion for FfiBuf data structure between Rust and C#. Additionally, it makes the C# class CoreNative internal for better encapsulation. Unnecessary call in MainWindow_OnLoaded has been removed.
  • Loading branch information
xorza committed May 20, 2024
1 parent 0ab33e2 commit c30b92a
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 50 deletions.
48 changes: 40 additions & 8 deletions ScenariumEditor.NET/CoreInterop/CoreNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,46 @@ public List<byte> ToList() {
return this.ToArray().ToList();
}

public T[] ToArray<T>() 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<T>();
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<T> ToList<T>() where T : unmanaged {
return this.ToArray<T>().ToList();
}

public void Dispose() {
if (bytes != null) {
Marshal.FreeHGlobal((IntPtr)bytes);
Expand All @@ -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);

Expand Down
10 changes: 2 additions & 8 deletions ScenariumEditor.NET/CoreInterop/CoreNative.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);


}
Expand Down
8 changes: 1 addition & 7 deletions ScenariumEditor.NET/CoreInterop/ScenariumCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,5 @@ public ScenariumCore() {
}
}


public String Test() {
var buf = CoreNative.test3();
var result = buf.ToString();
// buf.Dispose();
return result;
}

}
3 changes: 0 additions & 3 deletions ScenariumEditor.NET/ScenariumEditor.NET/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions cs_interop/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
51 changes: 27 additions & 24 deletions cs_interop/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<const N: usize, T> From<[T; N]> for FfiBuf
where
T: Clone,
{
fn from(data: [T; N]) -> Self {
data.to_vec().into()
}
}
impl<T> 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()
Expand Down Expand Up @@ -61,16 +63,17 @@ impl From<FfiBuf> for Vec<u8> {
unsafe { Vec::from_raw_parts(ptr, len, cap) }
}
}
impl From<Vec<u8>> for FfiBuf {
fn from(mut data: Vec<u8>) -> Self {
let len = data.len();
let cap = data.capacity();
impl<T> From<Vec<T>> for FfiBuf {
fn from(mut data: Vec<T>) -> Self {
let t_size = std::mem::size_of::<T>();
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,
}
Expand Down

0 comments on commit c30b92a

Please sign in to comment.