Reputation: 360
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;
}
}
}
Upvotes: 1
Views: 1521
Reputation: 360
This also works because I was able to define a C struct with the exact same layout as System.Drawing.PointF . Still unanswered is what if I needed to populate an array of C# classes from C++?
MonoArray* arrayPtF = mono_array_new(domain, ptFClass, 2);
struct cpoint {
float x, y;
} mycpoint[] = { { 42, 1701 }, { 1701, 42 } };
mono_array_set(arrayPtF, cpoint, 0, mycpoint[0]);
mono_array_set(arrayPtF, cpoint, 1, mycpoint[1]);
Upvotes: 1
Reputation: 360
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"
Upvotes: 2