When I googled around, I saw messages saying that passing a C # class same as passing a ref struct to the C API when using PInvoke (here is one of the C # PInvoke struct vs class access violation messages).
However, when I run the example, I see a different behavior than expected. Where the ref struct acts like a real pointer, while the "class" is not
C code:
//PInvokeProvider.h
Now in C # using struct for `Animal ':
namespace PInvokeConsumer { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct Animal { /// char[10000] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10000)] public string Name; public Animal(string name) { Name = name; } } public partial class NativeMethods { [DllImportAttribute("PInvokeProvider.dll", EntryPoint = "ChangeName", CallingConvention = CallingConvention.Cdecl)] public static extern void ChangeName(ref Animal pAnimal); } internal class Program { public static void Main(string[] args) { Animal animal = new Animal("Lion"); Console.WriteLine("Animal : {0}", animal.Name); Console.WriteLine("Leaving C#"); NativeMethods.ChangeName(ref animal); Console.WriteLine("Back to C#"); Console.WriteLine("Animal : {0}", animal.Name); Console.ReadKey(); } } }
The output using ref struct as expected, will change the first letter to "A" in the C # area:
Animal : Lion Leaving C
However, when I try to use class instead of ref struct :
namespace PInvokeConsumer { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class Animal { /// char[10000] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10000)] public string Name; public Animal(string name) { Name = name; } } public partial class NativeMethods { [DllImportAttribute("PInvokeProvider.dll", EntryPoint = "ChangeName", CallingConvention = CallingConvention.Cdecl)] public static extern void ChangeName(Animal pAnimal); } public static void Main(string[] args) { Animal animal = new Animal("Lion"); Console.WriteLine("Animal : {0}", animal.Name); Console.WriteLine("Leaving C#"); NativeMethods.ChangeName(animal); Console.WriteLine("Back to C#"); Console.WriteLine("Animal : {0}", animal.Name); Console.ReadKey(); } }
Output:
Animal : Lion Leaving C
Therefore, when I use the class, the memory allocated for Animal does not change. The question is why not?