#dotnet #managed #bindings #c-sharp #ffi

nightly rustishka

C#和Rust之间更好的互操作性

1个不稳定版本

0.1.0 2024年5月20日

#10 in #managed

MIT许可证

205KB
2.5K SLoC

Rustishka

本项目提供了一种与这些超级安全、超级快速的语言进行交互的酷方法!

Rust <===> C#在最高水平上互操作!

这种效果是通过在C#和Rust两边使用特殊库来实现的。

概述

C#端

该库为Rust库提供了与DotNet环境交互的小型接口。

private struct BridgeConvention
{
    public delegate* <object, Type> FGetType;
    public delegate* <string, bool, Type> FSearchType;
    public delegate* <Type, int, void*> FGetMethodAtSlot;
    public delegate* <Type, object> FAlloc;
    public delegate* <byte*, int, string> FAllocString;
    public delegate* <Type, int, Array> FAllocArray;
    public delegate* <delegate*<void>, Exception> FTryCatch;
    public delegate* <Exception, void> FThrow;
}

开发者必须通过函数调用将库连接到接口

RustishkaBridge.Bridge.ConnectRustModule(string libPath, out IntPtr moduleHandle) // to load lib and connect
// or
RustishkaBridge.Bridge.ConnectRustModule(IntPtr moduleHandle) // connect without loading. Use if the module has already been loaded before.

Rust端

开发者提供一个具有此签名的导出函数。它将在ConnectRustModule中调用

initialize_rustishka!();

重要事项

对于Rust中的具有类内容的结构,必须手动创建。

一个获取偏移量的工具

您也可以使用Sharplab。

功能

  • Rust库可以在DotNet运行时中搜索类型
let integer_type = search_type_cached(&String::from("System.Int32"), false);
  • Rust库可以分配对象和数组
let someType = search_type_cached(&someTypeAQN, false);
let obj: *mut NetObject<SomeType> = allocate(someType); // alloc without constructor invoke !!!
  • Rust库可以调用虚函数
let someType: *mut NetObject<SystemType> = ...;
let baseType = someType.get_base_type();

这以伪包装的形式呈现

define_virtual!(pub, get_base_type, 11, 4, *mut NetObject<SystemType>);

其中:11 - 行等于 slotId / 8,4 - 索引等于 slotId % 8

  • Rust库可以调用非虚实例和静态函数。
someObject.some_instance_method(args);
NetObject::<SomeObject>::some_static_method(args)
let val: *mut NetObject<SomeObject> = SomeObject::new(args);

其中

impl NetObject<SomeObject> {
   define_function!(pub some_instance_method, 7, self: *mut Self, arg_name: ArgType); // where 7 - slotId
   define_function!(pub some_static_method, 8, arg_name: ArgType);
}
impl SomeObject {
   define_constructor!(pub new, arg_name: ArgType);
}
  • Rust库可以访问静态字段
SomeObject::get_cool_static_field();
// where
define_typeof!(SomeObject, "blahblah");
impl SomeObject {
   define_static_field!(pub get_cool_static_field, "CoolStaticField", SomeFieldType);
}
  • Rust库可以使用typeof糖
pub struct SomeObject { }
define_typeof!(SomeObject, "SomeObject AssemblyQualifiedName");
// in method
let ty : *mut NetObject<SystemType> = SomeObject::type_of();
  • Rust库可以轻松分配托管数组
managed_array!(ElementType, elements num, elements);
// ex:
managed_array!(i32, 5, 0, 1, 2, 3, 4);
managed_array!(SystemType, 2, i32::type_of(), f32::type_of());
  • Rust库可以使用.NET反射的几乎所有功能!(甚至使用DynamicMethod!)

正如您所看到的:它非常人性化,非常容易使用。

示例

C#端

Rust端

待办事项

  • 添加对字段访问的支持
  • 通过创建通过.Net TypeBuilder创建的自定义类型并在Rust中通过方法表条目覆盖来支持.Net类型继承。
  • 源生成器(目前是Rustishka.Tools)

依赖关系

~110KB