嵌入式单声道:return / 将数组从 C# DLL 复制到 C++
Embedded mono: return / copy an array from C# DLL to C++
我有一个 C++ 应用程序,它应该使用 DLL 中的某些函数,该 DLL 是用 C# 编写并使用 mono 编译的。我已经想出如何从我的 C++ 代码中创建这些 C# 函数 运行,但仍然无法理解如何引用 C# 结果,该结果通常是 已知大小 [=37] 的数组=].
我的 C++ 代码如下所示:
MonoDomain* domain = mono_jit_init("CSharpDLLname.dll");
MonoAssembly* assembly = mono_domain_assembly_open(domain, "CSharpDLLname.dll");
MonoImage* image = mono_assembly_get_image(assembly);
MonoClass* klass = mono_class_from_name(image, "MyNamespace", "MyClass");
MonoObject* object = mono_object_new(domain, klass);
// call ctor
mono_runtime_object_init(object);
MonoMethodDesc* mdesc = mono_method_desc_new(":test(single[])", false);
MonoMethod* method = mono_method_desc_search_in_class(mdesc, klass);
void* args[1];
args[0] = &something;
// call function with provided args
mono_runtime_invoke(method, object, args, NULL);
// shutdown the runtime
mono_jit_cleanup (domain);
这是我在 C# DLL 中调用的函数类型:
public static float[] tester(float[] arr)
{
// ... do things to arr
// create an array of known size
float[] barr = new float[3];
barr[0] = 1;
barr[1] = 2;
barr[2] = 3;
// return it as result
return barr;
}
问题是如何从我的 C++ 代码中获取 barr
的指针或副本?
我尝试使用
MonoObject* returnObj = mono_runtime_invoke(method, object, args, NULL);
float* result = (float*)mono_object_unbox (returnObj);
但这会导致
Assertion at object.c:6493, condition `obj->vtable->klass->valuetype' not met.
...
Got a SIGABRT while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
如果我 return 像 public static float tester()
这样的单个值,那么它就可以工作并且我能够读取结果。现在我希望能够读取一个数组。
一个 C# 函数的简单 C+ 用法示例 return 数组会很棒。或者,如果 mono_runtime_invoke()
和 mono_object_unbox()
不是正确的方法(我是 C# 和单声道的初学者),很高兴知道如何正确地做到这一点 - 再次,基本示例表示赞赏。
我找不到关于如何 return 或复制整个数组的答案,但找到了其他方法。由于获取 blittable 类型是有效的,而不是 return 整个数组的函数,我用来获取数组的每个元素。例如:
C#代码:
private float[] m_array; // the array we want to copy to our C++ code
private int m_numElements; // length of the array
public static int getLength()
{
return m_numElements;
}
public static float[] getArray() // this will not work
{
return m_array;
}
public static float getArrayElement(int index) // we will use this instead!
{
return m_array[index];
}
C++代码中的用法:
MonoObject* lengthObj = mono_runtime_invoke(methodGetLength, object, NULL, NULL);
int length = *(int*)mono_object_unbox(lengthObj);
// now allocate the array where you will cope the result to
std::vector<float> array; // or could also be float[length]
array.resize(length);
for (int i=0; i<length; ++i){
void* args[1];
args[0] = &i;
// obtain the next element with index i
MonoObject* elementObj = mono_runtime_invoke(methodGetElement, object, args, NULL);
// copy the result to our array
array[i] = *(float*)mono_object_unbox(elementObj);
}
我有一个 C++ 应用程序,它应该使用 DLL 中的某些函数,该 DLL 是用 C# 编写并使用 mono 编译的。我已经想出如何从我的 C++ 代码中创建这些 C# 函数 运行,但仍然无法理解如何引用 C# 结果,该结果通常是 已知大小 [=37] 的数组=].
我的 C++ 代码如下所示:
MonoDomain* domain = mono_jit_init("CSharpDLLname.dll");
MonoAssembly* assembly = mono_domain_assembly_open(domain, "CSharpDLLname.dll");
MonoImage* image = mono_assembly_get_image(assembly);
MonoClass* klass = mono_class_from_name(image, "MyNamespace", "MyClass");
MonoObject* object = mono_object_new(domain, klass);
// call ctor
mono_runtime_object_init(object);
MonoMethodDesc* mdesc = mono_method_desc_new(":test(single[])", false);
MonoMethod* method = mono_method_desc_search_in_class(mdesc, klass);
void* args[1];
args[0] = &something;
// call function with provided args
mono_runtime_invoke(method, object, args, NULL);
// shutdown the runtime
mono_jit_cleanup (domain);
这是我在 C# DLL 中调用的函数类型:
public static float[] tester(float[] arr)
{
// ... do things to arr
// create an array of known size
float[] barr = new float[3];
barr[0] = 1;
barr[1] = 2;
barr[2] = 3;
// return it as result
return barr;
}
问题是如何从我的 C++ 代码中获取 barr
的指针或副本?
我尝试使用
MonoObject* returnObj = mono_runtime_invoke(method, object, args, NULL);
float* result = (float*)mono_object_unbox (returnObj);
但这会导致
Assertion at object.c:6493, condition `obj->vtable->klass->valuetype' not met. ... Got a SIGABRT while executing native code. This usually indicates a fatal error in the mono runtime or one of the native libraries used by your application.
如果我 return 像 public static float tester()
这样的单个值,那么它就可以工作并且我能够读取结果。现在我希望能够读取一个数组。
一个 C# 函数的简单 C+ 用法示例 return 数组会很棒。或者,如果 mono_runtime_invoke()
和 mono_object_unbox()
不是正确的方法(我是 C# 和单声道的初学者),很高兴知道如何正确地做到这一点 - 再次,基本示例表示赞赏。
我找不到关于如何 return 或复制整个数组的答案,但找到了其他方法。由于获取 blittable 类型是有效的,而不是 return 整个数组的函数,我用来获取数组的每个元素。例如:
C#代码:
private float[] m_array; // the array we want to copy to our C++ code
private int m_numElements; // length of the array
public static int getLength()
{
return m_numElements;
}
public static float[] getArray() // this will not work
{
return m_array;
}
public static float getArrayElement(int index) // we will use this instead!
{
return m_array[index];
}
C++代码中的用法:
MonoObject* lengthObj = mono_runtime_invoke(methodGetLength, object, NULL, NULL);
int length = *(int*)mono_object_unbox(lengthObj);
// now allocate the array where you will cope the result to
std::vector<float> array; // or could also be float[length]
array.resize(length);
for (int i=0; i<length; ++i){
void* args[1];
args[0] = &i;
// obtain the next element with index i
MonoObject* elementObj = mono_runtime_invoke(methodGetElement, object, args, NULL);
// copy the result to our array
array[i] = *(float*)mono_object_unbox(elementObj);
}