Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将数组从c#(Mono)封送到c++;_C#_C++_Arrays_Marshalling_Unityscript - Fatal编程技术网

将数组从c#(Mono)封送到c++;

将数组从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,

我尝试(非常)成功地将数组传递给我创建的dll。我在C语言中工作,在C++中进行一些机器学习操作。这里的问题是,我使用的是Mono而不是.Net framework(用于Unity)。我关注了多个“操作”链接,如和

第一个链接实际上非常有用,我可以把数组从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;
}