2011-02-10 66 views
0

我有這樣的代碼在C++中導入C++非託管的DLL到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); 

這樣不work.Any想法,請幫助,因爲我在編程新我不知道該怎麼辦it.Thanks 我把所有我從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); 


    } 
+0

我添加了C++代碼。有人幫助我必須給這個項目tommorow。 – 2011-02-10 19:10:03

回答

1

只要改變ref byte[] databyte[] data,我認爲它應該工作 - 其餘的似乎是正確的。

+0

它不起作用ii調用函數ConvertToByte(filename,Data);但Data數組最後是空的。爲什麼? – 2011-02-10 16:48:51

1

C++代碼不好:您正在設置data這是ConvertToByte函數中的一個參數。它沒有被傳遞出去。你至少可以以此爲出發點,對C++的一面:

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

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

}

調用者傳遞一個指針的指針的方式。該函數將指針指向該指針中的圖像數據。

+0

不起作用。我不明白爲什麼? – 2011-02-10 17:00:38

+0

它不起作用,因爲您現在必須根據您發佈的代碼發送一個指向我懷疑您沒有做的指針。大多數時候我會發送一個IntPtr的引用來實現這一點。您是否嘗試過使用您的發佈代碼對CallingConvention的建議? – 2011-02-10 18:13:31

2

嘗試使用:

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

注意使用Cdecl calling convention的:沒有它,P/Invoke的將承擔函數使用stdcall調用,並且無法清理堆棧。 (你也可以改變你的C函數的定義,包括__stdcall

然後,你可以通過字節*有:

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

不幸的是,你必須確保字節數組足夠大:(