在C ++中从char *获取C#中的byte []

时间:2014-06-27 14:23:52

标签: c# c++ dll marshalling

在C#中,我有一个数据类型byte[],我想用C ++函数填写char*

C ++函数(在ImageData.dll中)

char* pMemoryBuffer = NULL;
char* LoadData(const char *fileName)
{
    // processing pMemoryBuffer ...
    return pMemoryBuffer;  
}

将原生dll导入C#:

    [DllImport(".\\Modules_Native\\ImageData.dll", EntryPoint = "LoadData")]
   private extern static byte[] LoadData(string fileName);

C#中的byte[]数据

byte[] buffer = new byte[256*256];
buffer = LoadData("D:\\myPic.tif");

显然它还没有工作,但它提出了我想做的事情的想法。所以我想知道如何使这项工作,以及正确的方法是什么。非常感谢你的教育。

3 个答案:

答案 0 :(得分:5)

试试这个

// c++

    void LoadData(unsigned char* *pMemoryBuffer, const char *fileName)
    {
        // processing pMemoryBuffer ...
        *pMemoryBuffer = resutss;

    }

将原生dll导入C#:

[DllImport(".\\Modules_Native\\ImageData.dll", EntryPoint = "LoadData")]
private extern static void LoadData(out IntPtr data, string fileName);

当函数返回数据时,将指向数组,您可以使用Marshal类读取内容。我想你会copy it to a new byte arra y。

byte[] buffer = new byte[256*256];
buffer = Marshal.Copy(LoadData(buffer ,"D:\\myPic.tif"), buffer , 0, buffer.Length);

答案 1 :(得分:1)

我不确定,但我的直觉说你不能将char *分配给字节数组,就像在C ++本身中一样。你可以在C#中使用IntPtr(可能不是非常有用),或者,你可以传递C ++一个byte []缓冲区和一些要写入的字节。换句话说,我认为以下内容可行:

char* pMemoryBuffer = NULL;
int size = 0;
int seek = 0;
bool LoadData(const char* filename)
{
     // load filename
     // set seek = 0
     // set size to data size
}

int ReadData(char* buffer, int nBytesToRead)
{
    // nCopyBytes = min(nBytesToRead, size - seek)
    // copy nCopyBytes from pMemoryBuffer+seek to buffer
    // seek += nCopyBytes
    // return nCopyBytes
}

从C#开始,你会像这样使用它:

byte[] buffer = new byte[256*256];
LoadData("foo.tif");

int bytesRead = ReadData(buffer, 256*256);

很抱歉,如果你特别想避免做这样的事情。

答案 2 :(得分:1)

这应该这样做:

[DllImport(@".\Modules_Native\ImageData.dll")]
private extern static IntPtr LoadData(string fileName);

byte[] buffer = new byte[256*256];
buffer = Marshal.Copy(LoadData("D:\\myPic.tif"), buffer, 0, buffer.Length);

然而,它不会释放内存。希望C(++)库在下次调用期间自动释放它,否则提供释放函数。

更好的方法是使用调用者分配的缓冲区,然后你就可以:

byte[] buffer = new byte[256*256];
LoadData("D:\\myPic.tif", buffer);

为此,需要将C(++)代码更改为

int LoadData(const char *fileName, char* pMemoryBuffer)
{
    // processing pMemoryBuffer ...
    return 1;  // if success
}

和p / invoke声明到

[DllImport(@".\Modules_Native\ImageData.dll")]
private extern static int LoadData(string fileName, byte[] buffer);