1

I have the following C function that I need to call from C#:

__declspec(dllexport) int receive_message(char* ret_buf, int buffer_size);

I've declared the following on the C# side:

[DllImport("MyCLibrary", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, EntryPoint = "receive_message")]
public static extern int ReceiveMessage([MarshalAs(UnmanagedType.LPStr)]StringBuilder retBuf, int bufferSize);

I'm calling the function like so:

StringBuilder sb = new StringBuilder();
int len = ReceiveMessage(sb, 512);

This works fine with my initial tests where I was receiving "string" messages. But, now I want to receive packed messages (array of chars/bytes). The problem is that the array of chars/bytes will have 0s and will terminate the string so I don't get back the whole message. Any ideas how I can refactor to get array of bytes back?

4
  • Use Marshal.Copy(IntPtr source, byte[] destination, int startIndex, int length). Commented Apr 26, 2016 at 16:36
  • @jdweng, I'm not following. Do I need to change my extern declaration in my C#? Commented Apr 26, 2016 at 17:48
  • You are fibbing about the bufferSize argument, the Capacity of that StringBuilder is 0. The heap corruption that this can cause can be very unpleasant. If it is not actually a string then you must declare the 1st argument as byte[] instead. And same thing, pass its Length property as the 2nd argument. Commented Apr 26, 2016 at 17:57
  • I did notice my memory was slowly growing...maybe that was why. I think I figured out the Marshall.Copy that jdweng recommended. I'll post full answer once I confirm. Commented Apr 26, 2016 at 19:16

1 Answer 1

2

With jdweng help, I've changed the declaration to:

[DllImport("MyCLibrary", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, EntryPoint = "receive_message")]
public static extern int ReceiveMessage(IntPtr retBuf, int bufferSize);

And, I'm allocating and freeing the memory on the C# side along with marshalling the data.

IntPtr pnt = Marshall.AllocHGlobal(512);
try
{
   int len = ReceiveMessage(pnt, 512);
   ...
   byte[] bytes = new byte[len];
   Marshal.Copy(pnt, bytes, 0, len);
   ...
}
finally
{
   Marshal.FreeHGlobal(pnt);
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.