I'm trying to understand how to get a string from an unsafe byte pointer in the following struct. SDL_TEXTINPUTEVENT_TEXTSIZE is 32.
[StructLayout(LayoutKind.Sequential)]
public unsafe struct SDL_TextInputEvent
{
public SDL_EventType type;
public UInt32 timestamp;
public UInt32 windowID;
public fixed byte text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
}
I've tried:
byte[] rawBytes = new byte[SDL_TEXTINPUTEVENT_TEXT_SIZE];
unsafe
{
Marshal.Copy((IntPtr)rawEvent.text.text, rawBytes, 0, SDL_TEXTINPUTEVENT_TEXT_SIZE);
}
string text = System.Text.Encoding.UTF8.GetString(rawBytes);
Which kind of works, but gives me a string with a lot of extra bytes beyond the character that was actually entered. Should I parse the byte array and search for a 0-terminating character to avoid the excess?
Am I totally misunderstanding something?
For reference, the original C struct that is being marshaled into the .NET runtime is:
typedef struct SDL_TextInputEvent
{
Uint32 type;
Uint32 timestamp;
Uint32 windowID;
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
} SDL_TextInputEvent;
You do need to locate the null-terminator. And Marshal.Copy
will not do that. You could use Marshal.PtrToStringAnsi
if your text was ANSI encoded. But there's no such function for UTF-8. So you need to iterate over the array looking for a zero byte. When you encounter that you know the actual length of the buffer and you can modify your existing code to use that length rather than the maximum possible length.