I am passing a byte array from a function inside c DLL to a c# client. I am using a widely suggested method IntPtr pointer in C# and then Marshal.Copy to create byte array in the C# client. When I read the resulting array it seem I am getting random values. No actual values from the DLL are passed.
It seems the IntPnt is pointing at some random memory address?
Here is the code:
C DLL
extern "C" __declspec(dllexport) char* __stdcall passBytes() {
cout << "\n passBytes DLL code START \n";
char bytes[] = { 0x07, 0x08 };
cout << "bytes array size: " << sizeof(bytes) << endl;
for (int i = 0; i < sizeof(bytes); i ) {
cout << "byte " << i << " = " << (int)bytes[i] << endl;
}
char* bptr = bytes;
cout << "\n passBytes DLL code END \n";
return bptr;
}
C# client
namespace sc_client
{
class Program
{
static void Main(string[] args)
{
const string libname = "C:/work/x64/Release/libMxN.dll";
[DllImport(libname)]
static extern IntPtr passBytes();
IntPtr ptr = passBytes();
byte[] cbytes = new byte[2];
Marshal.Copy(ptr, cbytes, 0, 2);
Console.WriteLine("C# client output: ");
for ( int i = 0; i < cbytes.Length; i )
{
Console.WriteLine("client byte " i " = " (int)cbytes[i]);
}
}
}
}
Outputs ( just relaunched the app 4 times without any modifications in the code) 1. passBytes DLL code START bytes array size: 2 byte 0 = 7 byte 1 = 8
passBytes DLL code END
C# client output: client byte 0 = 176 client byte 1 = 232
2. passBytes DLL code START bytes array size: 2 byte 0 = 7 byte 1 = 8
passBytes DLL code END C# client output: client byte 0 = 144 client byte 1 = 232
3. passBytes DLL code START bytes array size: 2 byte 0 = 7 byte 1 = 8
passBytes DLL code END C# client output: client byte 0 = 176 client byte 1 = 228
CodePudding user response:
Your primary issue appears to be that the char*
array is declared locally, and disappears as soon as the function finishes. One way to do this properly is to allocate it on the heap, and make a separate Free
function.
But you are far better off just passing in a buffer. I'm not familiar with C very much, but something like this would be your function
extern "C" __declspec(dllexport) void __stdcall passBytes(char* bytes, int size) {
....
And then in C# you use it like this
const string libname = "C:/work/x64/Release/libMxN.dll";
[DllImport(libname)]
static extern void passBytes([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)][Out] byte[] bytes, int size);
static void Main(string[] args)
{
byte[] cbytes = new byte[2];
passBytes(cbytes, cbytes.Length);
Console.WriteLine("C# client output: ");
for ( int i = 0; i < cbytes.Length; i )
{
Console.WriteLine("client byte " i " = " (int)cbytes[i]);
}
}