Big_Bad_E
Big_Bad_E

Reputation: 847

Calling C# function throws "System.AccessViolationException"

This question is a more detailed version of another one

I'm trying to get a simple FFI communication between Rust and C#. The idea is to call a Rust function from C# and vice versa. Here's what I have:

public class Program
{
    [DllImport("D:\\Misc. CSharp\\NativeTesting\\Rust\\target\\debug\\test.dll")]
    public static extern void Test(IntPtr function);

    public static void TestFunction()
    {
        Console.WriteLine("Test!");
    }
    
    public delegate void TestDelegate();
    
    public static void Main()
    {
        Test(Marshal.GetFunctionPointerForDelegate((TestDelegate) TestFunction));
        Console.WriteLine("Done");
    }
}

This calls the Rust program:

#[no_mangle]
pub extern "C" fn Test(logger: &i8) {
    let function = logger.clone() as *const ();
    let function: fn() = unsafe { std::mem::transmute(function) };
    (function)();
}

This throws the following exception:

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
   at NativeTesting.Program.Test(IntPtr)
--------------------------------
   at NativeTesting.Program.Main()

I've looked through a ton of other FFI material, and haven't found any good solutions (reverse P/Invoke, linking the Rust to the C# dll, or using CLI), so please don't recommend any other tools to do this that I've mentioned.

Upvotes: 0

Views: 224

Answers (1)

Big_Bad_E
Big_Bad_E

Reputation: 847

The issue, as pointed out in the comments, is with the pointer. A * pointer is needed, not a & pointer.

New rust code:

#[no_mangle]
pub extern "C" fn Test(logger: *const i8) {
    let function: fn() = unsafe { std::mem::transmute(logger) };
    (function)();
}

Upvotes: 1

Related Questions