下面有一个C ++函数,它以unsigned char **
返回数据MyCPPFunc(unsigned char** ppData, int &nSize)
我想在C#中将它转换为float数组。问题是CPP返回的数据的内部表示可能是char \ ushort \ uint \ RGB等。如果我将使用如下,
var srcArray = new byte[nSize];
Marshal.Copy(pCPPData, srcArray, 0, nSize/4);
outDataArray = Array.ConvertAll<byte, float>(srcArray, Convert.ToSingle);
它会将每四个连续字节转换为浮点数,而内存中的数据可能具有不同的数据类型长度(可以是ushort,uchar,RGB等)
如何以最佳方式执行此操作,考虑到c ++库确实支持大量数据类型并在该类型的内存中返回数据。(尽管由uchar **表示)
我需要这样的东西,如下所示。其中dataTypeLen可以是1表示char,2表示简短,依此类推。
Array.Convert(pCPPData, 0, pFloatArray, dataTypeLen, floatArrLen);
不安全的代码也足够了。
答案 0 :(得分:0)
我不记得Marshaller中任何这样的智能转换器。除了一些粗体异常,如String或StringBuilder或Pointers / Handles本身,Marshaller不会转换数据类型。它获取一些字节并将它们解释为您请求的格式(数据类型)并返回您请求的格式(数据类型)。如果你要求它读取SHORT,它将解码为SHORT并返回SHORT。知道如何将CHAR转换为FLOAT是“不够智能”的。 这不仅仅是Marshaller的工作。而且,也不是任何标准转换器的工作。它们可以相互转换/转换简单类型(如double到decimal),但它们无法理解更复杂的结构,如“RGB”,或者更糟糕的是,某些RGB *填充到32位或BMP带填充行结束!
除非您使用某种智能转换器理解您输入的完全格式,否则您必须手动执行此操作。你首先需要准确地知道它是什么类型的数据(uchar,ushort,RGB等),然后以那种精确的格式接收(即编组)数组(uchar [],ushort [],..)然后你才将能够将元素转换为C#侧的浮点数。如果你尝试读取“就像那样”的字节,你可能会遇到endianess问题。当然,根据您的需要,您可能不在乎。
所以,例如:如果你知道pCPPData指向uchar数组,那么将其解组为uchar [];如果你知道pCPPData指向ushort数组,那么将其解组为ushort []; RGB?将其解组为bytes []或ints [],具体取决于单个颜色的bitdepth。然后,获取结果数组,在其上循环并转换为新的浮点数组。 (或者只是使用.Cast<float>().ToArray()
进行LINQize并忘记)。
然而,看起来有点开箱即用,你似乎与某种位图。 uchar-8bit灰度,ushort-16bit灰度,RGB-blah,我猜..那你为什么不尝试使用一些 Bitmap 处理器呢?我现在不记得了,但是.Net中有函数和类来处理/包装原始字节数组为Image
/ Bitmap
个对象。
例如,参见ie。 https://stackoverflow.com/a/16300450/717732或https://stackoverflow.com/a/9560495/717732 - 后者注意到评论,他们建议您甚至将scan0
设置为非托管指针,这样您就可以完全逃脱需要编组/复制任何东西。您可能会获得一个Bitmap对象,它直接从您从C ++库获得的指针读取 - 它将以您提供的ImageFormat
说明符指定的格式读取。我没有尝试过这个,所以我只说“可能”。
但是,当然,这不会给你float[]
而Bitmap
只有pixels
。如果你真的需要浮点数,那么你必须“手动”转换它:分支格式化,然后按格式指定读出它们,然后以你想要的格式存储它们。