Reputation: 1357
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
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
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
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