I need to pass an array from C++ to C# using mono. But I can’t get mono_array_set() to compile. So how can I pass an array from C++ to C#?
I’ve tried mono_runtime_invoke() which compiles but gives a runtime error.
mcs /nologo /warn:4 /debug:pdbonly /o /nowarn:3003 /platform:x64 /out:array.dll /target:library array.cs g++ array.cpp -g3 `pkg-config --cflags --libs mono-2` -o array <snip> array.cpp:32:5: note: in expansion of macro ‘mono_array_set’
// array.cpp #include <mono/jit/jit.h> #include <mono/metadata/assembly.h> #include <mono/metadata/debug-helpers.h> int main(int argc, char* argv[]) { MonoDomain* domain = mono_jit_init("./array.dll");; MonoAssembly* assembly = mono_domain_assembly_open(domain, "./array.dll"); MonoImage* image = mono_assembly_get_image(assembly); MonoClass* containsClass = mono_class_from_name(image, "IntArray", "ContainsAnInt"); MonoMethodDesc* containsDesc = mono_method_desc_new("IntArray.ContainsAnInt:.ctor(int)", false); MonoMethod* containsCtor = mono_method_desc_search_in_class(containsDesc, containsClass); MonoObject* containsObject = mono_object_new(domain, containsClass); void* args[1]; int value = 7; args[0] = &value; MonoObject* exception = NULL; mono_runtime_invoke(containsCtor, containsObject, args, &exception); MonoClass* unpackageClass = mono_class_from_name(image, "IntArray", "Unpackage"); args[0] = containsObject; MonoMethodDesc* returnIntDesc = mono_method_desc_new("IntArray.Unpackage:ReturnInt(IntArray.ContainsAnInt)", true); MonoMethod* returnIntMethod = mono_method_desc_search_in_class(returnIntDesc, unpackageClass); mono_runtime_invoke(returnIntMethod, NULL, args, &exception); // <--- as expected, outputs "In ReturnInt: 7" MonoArray* theArray = mono_array_new(domain, containsClass, 1); //// Following will not compile mono_array_set(theArray, MonoClass*, 0, containsObject); //// MonoMethodDesc* returnElementDesc = mono_method_desc_new("IntArray.Unpackage:ReturnElement(IntArray.ContainsAnInt[])", true); MonoMethod* returnElementMethod = mono_method_desc_search_in_class(returnElementDesc, unpackageClass); mono_runtime_invoke_array(returnElementMethod, NULL, theArray, &exception); // <--- should output "In ReturnElement: 7" mono_jit_cleanup(domain); }
// array.cs using System; using System.IO; namespace IntArray { public class ContainsAnInt { public ContainsAnInt(int i) { IntValue = i; } public int IntValue { get; set; } } public class Unpackage { public static int ReturnInt(ContainsAnInt n) { Console.WriteLine("In ReturnInt: " + n.IntValue); return n.IntValue; } public static int ReturnElement(ContainsAnInt[] n) { Console.WriteLine("In ReturnElement: " + n[0].IntValue); return n[0].IntValue; } } }
Advertisement
Answer
This works:
MonoArray* theArray = mono_array_new(domain, containsClass, 1); mono_array_set(theArray, MonoObject*, 0, containsObject); args[0] = theArray; mono_runtime_invoke(returnElementMethod, NULL, args, &exception); // <--- as expected, outputs "In ReturnElement: 7"