绑定到Monotouch中的第三方库 - 映射uint8_t *和uint8_t **

时间:2012-11-17 14:11:46

标签: c# c binding xamarin.ios

我正在尝试使用monotouch绑定到第三方条形码扫描库 - 除了以下方法之外,一切都运行良好,如库头文件中所定义的那样:

/**
 * Main scan function. Invokes all activated decoders by priority.
 * For successful scan, allocates pp_data buffer and pass it to user.
 * User should deallocate *pp_data pointer when no more needed.
 *
 * @param[in]   pp_image                Byte array representing grayscale value of image pixels.
 *                                      Array shold be stored in row after row fashion, starting with top row.
 * @param[in]   lenX                    X axis size (width) of image.
 * @param[in]   lenY                    Y axis size (length) of image.
 * @param[out]  pp_data                 On successful decode, library allocates new byte array where it stores decoded
 *                                      string result. Pointer to string is passed here. User application is responsible
 *                                      for deallocating this buffer after use.
 *
 * @retval      >0                      Result string length for successful decode
 * @retval      MWB_RT_BAD_PARAM        Null pointer or out of range parameters
 * @retval      MWB_RT_NOT_SUPPORTED    Unsupported decoder found in execution list - library error
 */
extern int MWB_scanGrayscaleImage(uint8_t *  pp_image,  int lenX,  int lenY, uint8_t **pp_data);

我已经有一段时间直接处理C数据结构了,我不清楚如何映射uint8_t * pp_imageuint8_t **pp_data

第一个参数处理来自像素缓冲区的灰度图像。我从CMSampleBuffer获得了一个图像缓冲区。是期望亮度转换的字节数组,字节数组的内存地址,还是将pixelBuffer.GetBaseAddress(0)传递为IntPtr就足够了?

最后一个参数在一个指针中传递,该指针在objective-C演示中被初始化为unsigned char *pResult=NULL;,然后在找到有效扫描时填充数据。同样,我不确定如何初始化并传入此内容,因为您无法在C#中传入未初始化的/ null字节数组。

我的绑定库代码目前如下(虽然我也尝试使用IntPtr,传递ref,并以不安全模式传递直接地址):

[DllImport ("__Internal")]
extern static int MWB_scanGrayscaleImage (byte[] pp_image, int lenX, int lenY, out byte[] pp_data);
public static int ScanGrayscaleImage (byte[] pp_image, int lenX, int lenY, out byte[] pp_data)
{
    int result = MWB_scanGrayscaleImage(pp_image, lenX, lenY, out pp_data);
    return result;
}

对于我到目前为止所尝试的所有内容,结果值一直返回-1,映射到“扫描失败”。任何帮助解决这个问题都将不胜感激。

2 个答案:

答案 0 :(得分:1)

第一个参数是保存亮度值的字节数组的内存地址,但是将数组作为参数传递应该这样做。

最后一个参数必须引用一个(有效)内存位置,其中将存储对输出字符串的引用。

您是否尝试过以下内容?

[DllImport ("__Internal")]
extern static int MWB_scanGrayscaleImage (byte[] pp_image, int lenX, int lenY, out byte[] pp_data);
public static int ScanGrayscaleImage (byte[] pp_image, int lenX, int lenY, out byte[] pp_data)
{
    int result;

    fixed (byte** pp_data_ptr = &pp_data) {
        result = MWB_scanGrayscaleImage(pp_image, lenX, lenY, pp_data_ptr);
    }

    return result;
}

答案 1 :(得分:1)

我建议将uint8_t **绑定为IntPtr,因为该库将无法分配托管字节[]

也许是这样的:

[DllImport ("__Internal")]
extern static int MWB_scanGrayscaleImage (byte[] pp_image, int lenX, int lenY, out IntPtr pp_data);
public static int ScanGrayscaleImage (byte[] image, int lenX, int lenY, out byte[] data)
{
    IntPtr pp_data;

    int result = MWB_scanGrayscaleImage (image, lenX, lenY, out pp_data);
    if (result > 0) {
        data = new byte[result];
        Marshal.Copy (pp_data, data, 0, result);
        Marshal.FreeHGlobal (pp_data); // I think this is what you want...
    } else {
        data = null;
    }

    return result;
}