将数组从c#(Mono)封送到c++;
我尝试(非常)成功地将数组传递给我创建的dll。我在C语言中工作,在C++中进行一些机器学习操作。这里的问题是,我使用的是Mono而不是.Net framework(用于Unity)。我关注了多个“操作”链接,如和将数组从c#(Mono)封送到c++;,c#,c++,arrays,marshalling,unityscript,C#,C++,Arrays,Marshalling,Unityscript,我尝试(非常)成功地将数组传递给我创建的dll。我在C语言中工作,在C++中进行一些机器学习操作。这里的问题是,我使用的是Mono而不是.Net framework(用于Unity)。我关注了多个“操作”链接,如和 第一个链接实际上非常有用,我可以把数组从C到C++传递到已知的边界,而这个数组不会被垃圾回收器消耗掉。但是,Mono中不支持SAFEARRAY(仅在.Net中) 我的c#代码的相关部分是: 我的问题: 调试DLL时,我会看到C++的垃圾。我还尝试从ItPtR切换到HANDLEFEF,
第一个链接实际上非常有用,我可以把数组从C到C++传递到已知的边界,而这个数组不会被垃圾回收器消耗掉。但是,Mono中不支持SAFEARRAY(仅在.Net中)
我的c#代码的相关部分是: 我的问题: 调试DLL时,我会看到C++的垃圾。我还尝试从ItPtR切换到HANDLEFEF,但是我不明白C++的工作需要做什么改变。顺便说一句,不管数组是否包装在结构中,任何传递数组而不被GC弄乱的方法都是可以的 我正在和所有有这个令人恼火的问题的天才接触我在C++边使用<>代码> STD::vector < /COD>和<代码> STD::向量< /代码> .< 重要的细节,需要在问题中。但是不,那永远不会起作用。C++语言类型没有互操作的故事,类实现细节在编译器实现之间完全不同。或者,在同一个编译器中变化太大。一个标准的辅助类迭代器调试改变C++标准库对象的布局。 Pinvoke互操作基于C语言类型。你现在的C#声明与
typedef struct LabeledData {
float* floatArray;
unsigned int* uintArray;
}
毫无疑问,你可以看到这个结构的大问题。没有任何合适的方法可以实际使用这些阵列。你不知道它们有多大。可以使用unMaundType。ByValAld阵列,但是等效的C++声明需要看起来:
typedef struct LabeledData {
float floatArray[42];
unsigned int uintArray[666];
}
毫无疑问,你会看到这个结构的大问题,数组长度是固定的。当您考虑std::vector时,您肯定不喜欢固定的数组长度
这就是.NET喜欢COM互操作类型的原因。SafeArray是安全的,因为它还存储数组长度。并且有一种定义良好的方法来分配和销毁它们,这是原始阵列的另一个大问题。如果没有它们,您所能做的就是:
typedef struct LabeledData {
size_t floatArraySize;
float* floatArray;
size_t uintArraySize;
unsigned int* uintArray;
}
并在C#侧将其与:
internal struct LabelData {
public int floatArraySize;
public IntPtr floatArray;
public int uintArraySize;
public IntPtr uintArray;
}
您需要Marshal.AllocHGlobal()来分配数组,您已经知道如何分配数组了。并担心谁和何时调用Marshal.FreeHGlobal()。因为您可能仍然希望保留std::vector,所以需要复制数组,以便在pinvoke调用后释放内存
当然,阵列数据复制非常非常难看。不要使用任何结构,而是使用四个功能。像CreateLabeledData、DestroyLabeledData、SetLabeledDataFloats、SetLabeledDataTaintegers。和一个相应的C++类,其中一个工厂方法实现这些函数。< /P> C++上的方法签名是什么?我在C++边使用STD::vector和STD::vector定义相同的结构。然后签名是:void DebugStruct(LabeledDataManaged*ptest_struct_和_数组),我认为问题在于创建结构的方式。我将尝试在没有封装结构的情况下编组单个数组,看看C++中的内存布局是否更容易理解。我想你也需要验证C和C++遵循的是相同的浮点标准。(尤其是在C++项目设置)@乔纳森,我已经尝试了同样的结果:(据我所知,unsigned int和float是可blittable的,因此标准是相同的。请注意,例如,使用SAFEARRAY时,数据被完美地转换了。@Leeor Link:www.mono-project.com/docs/advanced/pinvoke/“这样做的直接效果是,在封送类中不能有数组成员,并且(正如我们之前所看到的)处理字符串可能“不可靠”(因为字符串也是一种引用类型)。“简言之,在封送的类中不能有数组成员。这些都是很好的说明,我仔细地遵循了它们,它很有效!再次感谢
internal struct LabelData {
public int floatArraySize;
public IntPtr floatArray;
public int uintArraySize;
public IntPtr uintArray;
}