Импорт неуправляемой DLL-библиотеки c ++ в проблему c # - PullRequest
0 голосов
/ 10 февраля 2011

у меня есть этот код на C ++

   extern "C"
{
  __declspec(dllexport) void ConvertToByte(char *filename,unsigned char* data)

  {
       BITMAPINFO *info;
      data=(unsigned char *)LoadDIBitmap(filename, &info); 

  }
}

я хочу от c # дать имя файла и взять данные как?

 [DllImport("bmpToByte.dll", CharSet = CharSet.Ansi)]
    public static extern void ConvertToByte(string pame,ref byte[] data);

Этот способ не работает. Любая идея, пожалуйста, помогите, потому что я новичок в программировании, и я не знаю, как это сделать. Спасибо Я посылаю весь код, который я использую, из c ++. Может быть, у кого-то есть идея. Пожалуйста, помогите.

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include <windows.h>


void *
LoadDIBitmap(char       *filename, /* I - File to load */
             BITMAPINFO **info)    /* O - Bitmap information */
{
  FILE             *fp;            /* Open file pointer */
  void             *bits;          /* Bitmap pixel bits */
  long             bitsize,        /* Size of bitmap */
                   infosize;       /* Size of header information */
  BITMAPFILEHEADER header;         /* File header */

 /*
  * Try opening the file; use "rb" mode to read this *binary* file.
  */

  if ((fp = fopen(filename, "rb")) == NULL)
    return (NULL);

 /*
  * Read the file header and any following bitmap information…
  */

  if (fread(&header, sizeof(BITMAPFILEHEADER), 1, fp) < 1)
  {
   /*
    * Couldn't read the file header - return NULL…
    */

    fclose(fp);
    return (NULL);
  };

  if (header.bfType != 'MB') /* Check for BM reversed… */
  {
   /*
    * Not a bitmap file - return NULL…
    */

    fclose(fp);
    return (NULL);
  };
  infosize = header.bfOffBits - sizeof(BITMAPFILEHEADER);
  if ((*info = (BITMAPINFO *)malloc(infosize)) == NULL)
  {
   /*
    * Couldn't allocate memory for bitmap info - return NULL…
    */

    fclose(fp);
    return (NULL);
  };

  if (fread(*info, 1, infosize, fp) < infosize)
  {
   /*
    * Couldn't read the bitmap header - return NULL…
    */

    free(*info);
    fclose(fp);
    return (NULL);
  };

 /*
  * Now that we have all the header info read in, allocate memory for the
  * bitmap and read *it* in…
  */

  if ((bitsize = (*info)->bmiHeader.biSizeImage) == 0)
    bitsize = ((*info)->bmiHeader.biWidth *
               (*info)->bmiHeader.biBitCount + 7) / 8 *
        abs((*info)->bmiHeader.biHeight);

  if ((bits = malloc(bitsize)) == NULL)
  {
   /*
    * Couldn't allocate memory - return NULL!
    */

    free(*info);
    fclose(fp);
    return (NULL);
  };

  if (fread(bits, 1, bitsize, fp) < bitsize)
  {
   /*
    * Couldn't read bitmap - free memory and return NULL!
    */

    free(*info);
    free(bits);
    fclose(fp);
    return (NULL);
  };

 /*
  * OK, everything went fine - return the allocated bitmap…
  */

  fclose(fp);
  return (bits);
}


int
SaveDIBitmap(char       *filename, /* I - File to save to */
             BITMAPINFO *info,     /* I - Bitmap information */
             void       *bits)     /* I - Bitmap pixel bits */
{
  FILE             *fp;            /* Open file pointer */
  long             size,           /* Size of file */
                   infosize,       /* Size of bitmap info */
                   bitsize;        /* Size of bitmap pixels */
  BITMAPFILEHEADER header;         /* File header */

 /*
  * Try opening the file; use "wb" mode to write this *binary* file.
  */

  if ((fp = fopen(filename, "wb")) == NULL)
    return (-1);

  if (info->bmiHeader.biSizeImage == 0)/* Figure out the bitmap size */
    bitsize = (info->bmiHeader.biWidth *
               info->bmiHeader.biBitCount + 7) / 8 *
      abs(info->bmiHeader.biHeight);
  else
    bitsize = info->bmiHeader.biSizeImage;

  infosize = sizeof(BITMAPINFOHEADER);
  switch (info->bmiHeader.biCompression)
  {
    case BI_BITFIELDS :
        infosize += 12; /* Add 3 RGB doubleword masks */
        if (info->bmiHeader.biClrUsed == 0)
          break;
    case BI_RGB :
        if (info->bmiHeader.biBitCount > 8 &&
            info->bmiHeader.biClrUsed == 0)
          break;
    case BI_RLE8 :
    case BI_RLE4 :
        if (info->bmiHeader.biClrUsed == 0)
          infosize += (1 << info->bmiHeader.biBitCount) * 4;
        else
          infosize += info->bmiHeader.biClrUsed * 4;
        break;
  };

  size = sizeof(BITMAPFILEHEADER) + infosize + bitsize;

 /*
  * Write the file header, bitmap information, and bitmap pixel data…
  */

  header.bfType      = 'MB'; /* Non-portable… sigh */
  header.bfSize      = size;
  header.bfReserved1 = 0;
  header.bfReserved2 = 0;
  header.bfOffBits   = sizeof(BITMAPFILEHEADER) + infosize;
  if (fwrite(&header, 1, sizeof(BITMAPFILEHEADER), fp) <
          sizeof(BITMAPFILEHEADER))
  {
   /*
    * Couldn't write the file header - return…
    */

    fclose(fp);
    return (-1);
  };
  int l;
  if (l=fwrite(info, 1, infosize, fp) < infosize)
  {
   /*
    * Couldn't write the bitmap header - return…
    */

    fclose(fp);
    return (-1);
  };

  if (l=fwrite(bits, 1, bitsize, fp) < bitsize)
  {
   /*
    * Couldn't write the bitmap - return…
    */

    fclose(fp);
    return (-1);
  };

 /*
  * OK, everything went fine - return…
  */

  fclose(fp);
  return (0);
}

extern "C"
{
  __declspec(dllexport) void ConvertToByte(char *filename,unsigned char** data)

  {
      char temp[100];
      sprintf(temp,filename);
       BITMAPINFO *info;
      *data=(unsigned char *)LoadDIBitmap(temp, &info); 


  }

Ответы [ 3 ]

2 голосов
/ 10 февраля 2011

Попробуйте использовать:

 [DllImport("bmpToByte.dll", CharSet = CharSet.Ansi, 
                             CallingConvention = CallingConvention.Cdecl)]
    unsafe static extern void ConvertToByte(string pame,byte* data);

Обратите внимание на использование соглашения о вызовах Cdecl : без него P / Invoke предполагает, что функция использует соглашение о вызовах stdcall, и не сможет очистить стек. (Вы также можете изменить определение вашей функции C, включив __stdcall)

Затем вы можете передать байт * с помощью:

byte[] data = new byte[100000]
fixed (byte* p = data)
    {
        ConvertToByte(..., p);
    }

К сожалению, вы должны убедиться, что байтовый массив достаточно большой: (* ​​1014 *

1 голос
/ 10 февраля 2011

Код C ++ не годится: вы устанавливаете data, который является параметром в функции ConvertToByte.Это не прошло.Вы можете использовать это как отправную точку, по крайней мере для стороны C ++:

extern "C"
{
  __declspec(dllexport) void ConvertToByte(char *filename,unsigned char** data)

  {
       BITMAPINFO *info;
       *data=(unsigned char *)LoadDIBitmap(filename, &info); 
  }

}

Таким образом, вызывающая сторона передает указатель на указатель.Функция помещает указатель на данные изображения в этом указателе.

1 голос
/ 10 февраля 2011

Просто измените ref byte[] data на byte[] data и я думаю, что это должно сработать - остальное кажется правильным.

...