嵌入式单声道:将数组从 C# DLL 返回/复制到 C++

Posted

技术标签:

【中文标题】嵌入式单声道:将数组从 C# DLL 返回/复制到 C++【英文标题】:Embedded mono: return / copy an array from C# DLL to C++ 【发布时间】:2017-10-10 23:13:32 【问题描述】:

我有一个 C++ 应用程序,它应该使用 DLL 中的某些函数,该 DLL 是用 C# 编写并使用 mono 编译的。我已经想出了如何让这些 C# 函数从我的 C++ 代码中运行,但仍然无法理解如何引用通常是 已知大小 的数组的 C# 结果。

我的 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);

但这会导致

object.c:6493 处的断言,条件 `obj->vtable->klass->valuetype' 未满足。 ... 执行本机代码时收到 SIGABRT。这通常表明 单声道运行时或本机库之一中的致命错误 由您的应用程序使用。

如果我返回像public static float tester() 这样的单个值,那么它可以工作并且我能够读取结果。现在我希望能够读取一个数组。

返回数组的 C# 函数的简单 C+ 用法示例会很棒。或者,如果 mono_runtime_invoke()mono_object_unbox() 不是正确的方法(我是 C# 和单声道的初学者),我很高兴知道如何正确地做到这一点 - 再次感谢基本示例。

【问题讨论】:

【参考方案1】:

我找不到关于如何返回或复制整个数组的答案,但我想出了另一种方法。由于获取 blittable 类型是有效的,而不是返回整个数组的函数,我曾经获取数组的每个元素。例如:

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 返回/复制到 C++的主要内容,如果未能解决你的问题,请参考以下文章

将字节数组从 c++ 传递到 c#(单声道)

通过单声道将数组从 C++ 传递给 C#

使用 C#“输出参数”嵌入单声道

单声道嵌入,从 C 调用 C# 泛型方法

如何使用嵌入在 C++ 中的单声道编译 C# 代码?

将参数从 C 传递到 Embedded Mono