1

下面有一个 C++ 函数,它以 unsigned char 格式返回数据**

MyCPPFunc(unsigned char** ppData, int &nSize)

我想将它转换为 C# 中的浮点数组。问题是 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 代表 short 等等。

Array.Convert(pCPPData, 0, pFloatArray, dataTypeLen, floatArrLen);

不安全的代码也足够了。

4

1 回答 1

0

我不记得Marshaller中有任何这样聪明的Convert'er。除了一些粗体例外,如 String 或 StringBuilder 或 Pointers/Handles 本身,Marshaller 不会转换数据类型。它获取一些字节并将它们解释为您请求的格式(数据类型)并返回您请求的格式(数据类型)。如果您要求它读取 SHORT,那么它将解码为 SHORT 并返回一个 SHORT。知道如何将 CHAR 转换为 FLOAT 是“不够聪明”的。这不是 Marshaller 的工作。而且,也不是任何标准转换器的工作。他们可以相互转换/转换简单类型(如 double 到 decimal),但他们将无法理解更复杂的结构,如“RGB”,或者更糟糕的是,一些 RGB* 填充为 32 位或 BMP 填充为行尾!

除非您采用一些能够理解您输入的确切格式的智能转换器,否则您必须手动完成。您首先需要准确地知道它是什么类型的数据(uchar、ushort、RGB 等),然后以该精确格式(uchar[]、ushort[]、..)接收(即编组)数组,然后才可以将能够在 C# 端将元素转换为浮点数。如果您尝试“像那样”读取字节,您可能会遇到字节序问题。当然,你可能不在乎,这取决于你的需要。

因此,例如:如果您知道 pCPPData 指向 uchar 数组,则将其解组为 uchar[]; 如果您知道 pCPPData 指向 ushort 数组,则将其解组为 ushort[]; RGB?根据单个颜色的位深度,将其解组为 bytes[] 或 ints[]。然后,获取结果数组,对其进行循环并转换为一个新的浮点数组。(或者,只是 LINQize.Cast<float>().ToArray()并忘记)。

但是,看起来有点开箱即用,您似乎使用某种位图。uchar-8bit grayscale, ushort-16bit grayscale, RGB-blah, 我猜.. 那么你为什么不尝试使用一些Bitmap处理器呢?我现在不记得了,但是 .Net 中有将原始字节数组处理/包装为Image/Bitmap对象的函数和类。

例如,参见 ie。https://stackoverflow.com/a/16300450/717732https://stackoverflow.com/a/9560495/717732 - 在后者中注意注释,他们建议您甚至可以将 设置scan0为非托管指针,因此您可能完全不需要编组/复制任何东西。您可能会得到一个 Bitmap 对象,该对象直接从您从 C++ 库中获得的指针读取 - 并且它将以ImageFormat您提供的说明符指定的格式读取。我从来没有试过这个,所以我只说“可能”。

但是,当然,那不会给你,float[]而是. 如果你真的需要浮点数,那么你必须“手动”转换它:分支格式,然后按照格式指定读取它们,然后以你想要的格式存储它们。Bitmappixels

于 2013-11-13T12:03:09.133 回答