Ono
Ono

Reputation: 1357

Get byte[] in C# from char* in C++

In C# I have an data type byte[], which I want to fill in using a C++ function which returns char*

The C++ function (in ImageData.dll)

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

Import native dll into C#:

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

The byte[] data in C#

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

Apparently it is not working yet, but it presents the idea of what I want to do. So I am wondering how to make this work, and what is the right way to do it. Thanks very much for your education.

Upvotes: 2

Views: 6230

Answers (3)

Patrick87
Patrick87

Reputation: 28292

I'm not sure, but my gut says that you can't assign a char* to a byte array, just as you can't in C++ itself. You can either use an IntPtr in C# (probably not super useful), OR, you can pass C++ a byte[] buffer and a number of bytes to write. In other words, I think the following would work:

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
}

From C#, you'd use it like this:

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

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

Sorry if you specifically want to avoid doing something like this.

Upvotes: 1

MRebai
MRebai

Reputation: 5474

try this

// c++

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

    }

Import native dll into C#:

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

When the function returns data will point to the array and you can read the contents using the Marshal class. I guess you would copy it to a new byte array.

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

Upvotes: 6

Ben Voigt
Ben Voigt

Reputation: 283614

This should do it:

[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);

However, it won't free the memory. Hopefully the C(++) library frees it automatically during the next call, or else provides a deallocation function.

A better approach is to use a caller-allocated buffer, then you would just do:

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

For this, the C(++) code would need to be changed to

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

and the p/invoke declaration to

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

Upvotes: 1

Related Questions