Avoid string and byte[] allocation when converting to UTF8 native string (#192)

This commit is contained in:
Chad Yates 2020-05-21 07:00:19 -07:00 committed by GitHub
parent 8d0760016b
commit 040d39b4a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 348 additions and 185 deletions

View file

@ -28,7 +28,9 @@
#region Using Statements #region Using Statements
using System; using System;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
#endregion #endregion
namespace SDL2 namespace SDL2
@ -43,19 +45,66 @@ namespace SDL2
#region UTF8 Marshaling #region UTF8 Marshaling
internal static byte[] UTF8_ToNative(string s) /* Used for stack allocated string marshaling. */
internal static int Utf8Size(string str)
{ {
if (s == null) Debug.Assert(str != null);
return (str.Length * 4) + 1;
}
internal static int Utf8SizeNullable(string str)
{ {
return null; return str != null ? (str.Length * 4) + 1 : 0;
}
internal static unsafe byte* Utf8Encode(string str, byte* buffer, int bufferSize)
{
Debug.Assert(str != null);
fixed (char* strPtr = str)
{
Encoding.UTF8.GetBytes(strPtr, str.Length + 1, buffer, bufferSize);
}
return buffer;
}
internal static unsafe byte* Utf8EncodeNullable(string str, byte* buffer, int bufferSize)
{
if (str == null)
{
buffer[0] = 0;
return buffer;
}
fixed (char* strPtr = str)
{
Encoding.UTF8.GetBytes(strPtr, str.Length + 1, buffer, bufferSize);
}
return buffer;
} }
// Add a null terminator. That's kind of it... :/ /* Used for heap allocated string marshaling.
return System.Text.Encoding.UTF8.GetBytes(s + '\0'); * Returned byte* must be free'd with FreeHGlobal.
*/
internal static unsafe byte* Utf8Encode(string str)
{
Debug.Assert(str != null);
int bufferSize = Utf8Size(str);
byte* buffer = (byte*)Marshal.AllocHGlobal(bufferSize);
fixed (char* strPtr = str)
{
Encoding.UTF8.GetBytes(strPtr, str.Length + 1, buffer, bufferSize);
}
return buffer;
}
internal static unsafe byte* Utf8EncodeNullable(string str)
{
int bufferSize = Utf8SizeNullable(str);
byte* buffer = (byte*)Marshal.AllocHGlobal(bufferSize);
fixed (char* strPtr = str)
{
Encoding.UTF8.GetBytes(strPtr, str != null ? str.Length + 1 : 0, buffer, bufferSize);
}
return buffer;
} }
/* This is public because SDL_DropEvent needs it! */ /* This is public because SDL_DropEvent needs it! */
public static unsafe string UTF8_ToManaged(IntPtr s, bool freePtr = false) internal static unsafe string UTF8_ToManaged(IntPtr s, bool freePtr = false)
{ {
if (s == IntPtr.Zero) if (s == IntPtr.Zero)
{ {
@ -205,18 +254,23 @@ namespace SDL2
/* IntPtr refers to an SDL_RWops* */ /* IntPtr refers to an SDL_RWops* */
[DllImport(nativeLibName, EntryPoint = "SDL_RWFromFile", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_RWFromFile", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_SDL_RWFromFile( private static extern unsafe IntPtr INTERNAL_SDL_RWFromFile(
byte[] file, byte* file,
byte[] mode byte* mode
); );
public static IntPtr SDL_RWFromFile( public static unsafe IntPtr SDL_RWFromFile(
string file, string file,
string mode string mode
) { ) {
return INTERNAL_SDL_RWFromFile( byte* utf8File = Utf8Encode(file);
UTF8_ToNative(file), byte* utf8Mode = Utf8Encode(mode);
UTF8_ToNative(mode) IntPtr rwOps = INTERNAL_SDL_RWFromFile(
utf8File,
utf8Mode
); );
Marshal.FreeHGlobal((IntPtr)utf8Mode);
Marshal.FreeHGlobal((IntPtr)utf8File);
return rwOps;
} }
/* IntPtr refers to an SDL_RWops* */ /* IntPtr refers to an SDL_RWops* */
@ -610,59 +664,75 @@ namespace SDL2
public static extern void SDL_ClearHints(); public static extern void SDL_ClearHints();
[DllImport(nativeLibName, EntryPoint = "SDL_GetHint", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GetHint", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_SDL_GetHint(byte[] name); private static extern unsafe IntPtr INTERNAL_SDL_GetHint(byte* name);
public static string SDL_GetHint(string name) public static unsafe string SDL_GetHint(string name)
{ {
int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
return UTF8_ToManaged( return UTF8_ToManaged(
INTERNAL_SDL_GetHint( INTERNAL_SDL_GetHint(
UTF8_ToNative(name) Utf8Encode(name, utf8Name, utf8NameBufSize)
) )
); );
} }
[DllImport(nativeLibName, EntryPoint = "SDL_SetHint", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_SetHint", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_bool INTERNAL_SDL_SetHint( private static extern unsafe SDL_bool INTERNAL_SDL_SetHint(
byte[] name, byte* name,
byte[] value byte* value
); );
public static SDL_bool SDL_SetHint(string name, string value) public static unsafe SDL_bool SDL_SetHint(string name, string value)
{ {
int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
int utf8ValueBufSize = Utf8Size(value);
byte* utf8Value = stackalloc byte[utf8ValueBufSize];
return INTERNAL_SDL_SetHint( return INTERNAL_SDL_SetHint(
UTF8_ToNative(name), Utf8Encode(name, utf8Name, utf8NameBufSize),
UTF8_ToNative(value) Utf8Encode(value, utf8Value, utf8ValueBufSize)
); );
} }
[DllImport(nativeLibName, EntryPoint = "SDL_SetHintWithPriority", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_SetHintWithPriority", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_bool INTERNAL_SDL_SetHintWithPriority( private static extern unsafe SDL_bool INTERNAL_SDL_SetHintWithPriority(
byte[] name, byte* name,
byte[] value, byte* value,
SDL_HintPriority priority SDL_HintPriority priority
); );
public static SDL_bool SDL_SetHintWithPriority( public static unsafe SDL_bool SDL_SetHintWithPriority(
string name, string name,
string value, string value,
SDL_HintPriority priority SDL_HintPriority priority
) { ) {
int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
int utf8ValueBufSize = Utf8Size(value);
byte* utf8Value = stackalloc byte[utf8ValueBufSize];
return INTERNAL_SDL_SetHintWithPriority( return INTERNAL_SDL_SetHintWithPriority(
UTF8_ToNative(name), Utf8Encode(name, utf8Name, utf8NameBufSize),
UTF8_ToNative(value), Utf8Encode(value, utf8Value, utf8ValueBufSize),
priority priority
); );
} }
/* Only available in 2.0.5 or higher. */ /* Only available in 2.0.5 or higher. */
[DllImport(nativeLibName, EntryPoint = "SDL_GetHintBoolean", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GetHintBoolean", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_bool INTERNAL_SDL_GetHintBoolean( private static extern unsafe SDL_bool INTERNAL_SDL_GetHintBoolean(
byte[] name, byte* name,
SDL_bool default_value SDL_bool default_value
); );
public static SDL_bool SDL_GetHintBoolean( public static unsafe SDL_bool SDL_GetHintBoolean(
string name, string name,
SDL_bool default_value SDL_bool default_value
) { ) {
int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
return INTERNAL_SDL_GetHintBoolean( return INTERNAL_SDL_GetHintBoolean(
UTF8_ToNative(name), Utf8Encode(name, utf8Name, utf8NameBufSize),
default_value default_value
); );
} }
@ -683,11 +753,13 @@ namespace SDL2
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_SetError", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_SetError", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_SetError(byte[] fmtAndArglist); private static extern unsafe void INTERNAL_SDL_SetError(byte* fmtAndArglist);
public static void SDL_SetError(string fmtAndArglist) public static unsafe void SDL_SetError(string fmtAndArglist)
{ {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_SetError( INTERNAL_SDL_SetError(
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
@ -752,145 +824,163 @@ namespace SDL2
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_Log", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_Log", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_Log(byte[] fmtAndArglist); private static extern unsafe void INTERNAL_SDL_Log(byte* fmtAndArglist);
public static void SDL_Log(string fmtAndArglist) public static unsafe void SDL_Log(string fmtAndArglist)
{ {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_Log( INTERNAL_SDL_Log(
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogVerbose", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogVerbose", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogVerbose( private static extern unsafe void INTERNAL_SDL_LogVerbose(
int category, int category,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogVerbose( public static unsafe void SDL_LogVerbose(
int category, int category,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogVerbose( INTERNAL_SDL_LogVerbose(
category, category,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogDebug", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogDebug", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogDebug( private static extern unsafe void INTERNAL_SDL_LogDebug(
int category, int category,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogDebug( public static unsafe void SDL_LogDebug(
int category, int category,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogDebug( INTERNAL_SDL_LogDebug(
category, category,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogInfo", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogInfo", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogInfo( private static extern unsafe void INTERNAL_SDL_LogInfo(
int category, int category,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogInfo( public static unsafe void SDL_LogInfo(
int category, int category,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogInfo( INTERNAL_SDL_LogInfo(
category, category,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogWarn", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogWarn", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogWarn( private static extern unsafe void INTERNAL_SDL_LogWarn(
int category, int category,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogWarn( public static unsafe void SDL_LogWarn(
int category, int category,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogWarn( INTERNAL_SDL_LogWarn(
category, category,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogError", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogError", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogError( private static extern unsafe void INTERNAL_SDL_LogError(
int category, int category,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogError( public static unsafe void SDL_LogError(
int category, int category,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogError( INTERNAL_SDL_LogError(
category, category,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogCritical", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogCritical", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogCritical( private static extern unsafe void INTERNAL_SDL_LogCritical(
int category, int category,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogCritical( public static unsafe void SDL_LogCritical(
int category, int category,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogCritical( INTERNAL_SDL_LogCritical(
category, category,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogMessage", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogMessage", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogMessage( private static extern unsafe void INTERNAL_SDL_LogMessage(
int category, int category,
SDL_LogPriority priority, SDL_LogPriority priority,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogMessage( public static unsafe void SDL_LogMessage(
int category, int category,
SDL_LogPriority priority, SDL_LogPriority priority,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogMessage( INTERNAL_SDL_LogMessage(
category, category,
priority, priority,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
/* Use string.Format for arglists */ /* Use string.Format for arglists */
[DllImport(nativeLibName, EntryPoint = "SDL_LogMessageV", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_LogMessageV", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_LogMessageV( private static extern unsafe void INTERNAL_SDL_LogMessageV(
int category, int category,
SDL_LogPriority priority, SDL_LogPriority priority,
byte[] fmtAndArglist byte* fmtAndArglist
); );
public static void SDL_LogMessageV( public static unsafe void SDL_LogMessageV(
int category, int category,
SDL_LogPriority priority, SDL_LogPriority priority,
string fmtAndArglist string fmtAndArglist
) { ) {
int utf8FmtAndArglistBufSize = Utf8Size(fmtAndArglist);
byte* utf8FmtAndArglist = stackalloc byte[utf8FmtAndArglistBufSize];
INTERNAL_SDL_LogMessageV( INTERNAL_SDL_LogMessageV(
category, category,
priority, priority,
UTF8_ToNative(fmtAndArglist) Utf8Encode(fmtAndArglist, utf8FmtAndArglist, utf8FmtAndArglistBufSize)
); );
} }
@ -1094,22 +1184,28 @@ namespace SDL2
/* window refers to an SDL_Window* */ /* window refers to an SDL_Window* */
[DllImport(nativeLibName, EntryPoint = "SDL_ShowSimpleMessageBox", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_ShowSimpleMessageBox", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_SDL_ShowSimpleMessageBox( private static extern unsafe int INTERNAL_SDL_ShowSimpleMessageBox(
SDL_MessageBoxFlags flags, SDL_MessageBoxFlags flags,
byte[] title, byte* title,
byte[] message, byte* message,
IntPtr window IntPtr window
); );
public static int SDL_ShowSimpleMessageBox( public static unsafe int SDL_ShowSimpleMessageBox(
SDL_MessageBoxFlags flags, SDL_MessageBoxFlags flags,
string title, string title,
string message, string message,
IntPtr window IntPtr window
) { ) {
int utf8TitleBufSize = Utf8SizeNullable(title);
byte* utf8Title = stackalloc byte[utf8TitleBufSize];
int utf8MessageBufSize = Utf8SizeNullable(message);
byte* utf8Message = stackalloc byte[utf8MessageBufSize];
return INTERNAL_SDL_ShowSimpleMessageBox( return INTERNAL_SDL_ShowSimpleMessageBox(
flags, flags,
UTF8_ToNative(title), Utf8EncodeNullable(title, utf8Title, utf8TitleBufSize),
UTF8_ToNative(message), Utf8EncodeNullable(message, utf8Message, utf8MessageBufSize),
window window
); );
} }
@ -1344,15 +1440,15 @@ namespace SDL2
/* IntPtr refers to an SDL_Window* */ /* IntPtr refers to an SDL_Window* */
[DllImport(nativeLibName, EntryPoint = "SDL_CreateWindow", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_CreateWindow", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_SDL_CreateWindow( private static extern unsafe IntPtr INTERNAL_SDL_CreateWindow(
byte[] title, byte* title,
int x, int x,
int y, int y,
int w, int w,
int h, int h,
SDL_WindowFlags flags SDL_WindowFlags flags
); );
public static IntPtr SDL_CreateWindow( public static unsafe IntPtr SDL_CreateWindow(
string title, string title,
int x, int x,
int y, int y,
@ -1360,8 +1456,10 @@ namespace SDL2
int h, int h,
SDL_WindowFlags flags SDL_WindowFlags flags
) { ) {
int utf8TitleBufSize = Utf8SizeNullable(title);
byte* utf8Title = stackalloc byte[utf8TitleBufSize];
return INTERNAL_SDL_CreateWindow( return INTERNAL_SDL_CreateWindow(
UTF8_ToNative(title), Utf8EncodeNullable(title, utf8Title, utf8TitleBufSize),
x, y, w, h, x, y, w, h,
flags flags
); );
@ -1521,17 +1619,19 @@ namespace SDL2
/* window refers to an SDL_Window*, IntPtr to a void* */ /* window refers to an SDL_Window*, IntPtr to a void* */
[DllImport(nativeLibName, EntryPoint = "SDL_GetWindowData", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GetWindowData", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_SDL_GetWindowData( private static extern unsafe IntPtr INTERNAL_SDL_GetWindowData(
IntPtr window, IntPtr window,
byte[] name byte* name
); );
public static IntPtr SDL_GetWindowData( public static unsafe IntPtr SDL_GetWindowData(
IntPtr window, IntPtr window,
string name string name
) { ) {
int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
return INTERNAL_SDL_GetWindowData( return INTERNAL_SDL_GetWindowData(
window, window,
UTF8_ToNative(name) Utf8Encode(name, utf8Name, utf8NameBufSize)
); );
} }
@ -1648,23 +1748,28 @@ namespace SDL2
/* IntPtr refers to a function pointer */ /* IntPtr refers to a function pointer */
[DllImport(nativeLibName, EntryPoint = "SDL_GL_GetProcAddress", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GL_GetProcAddress", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_SDL_GL_GetProcAddress( private static extern unsafe IntPtr INTERNAL_SDL_GL_GetProcAddress(
byte[] proc byte* proc
); );
public static IntPtr SDL_GL_GetProcAddress(string proc) public static unsafe IntPtr SDL_GL_GetProcAddress(string proc)
{ {
int utf8ProcBufSize = Utf8Size(proc);
byte* utf8Proc = stackalloc byte[utf8ProcBufSize];
return INTERNAL_SDL_GL_GetProcAddress( return INTERNAL_SDL_GL_GetProcAddress(
UTF8_ToNative(proc) Utf8Encode(proc, utf8Proc, utf8ProcBufSize)
); );
} }
[DllImport(nativeLibName, EntryPoint = "SDL_GL_LoadLibrary", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GL_LoadLibrary", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_SDL_GL_LoadLibrary(byte[] path); private static extern unsafe int INTERNAL_SDL_GL_LoadLibrary(byte* path);
public static int SDL_GL_LoadLibrary(string path) public static unsafe int SDL_GL_LoadLibrary(string path)
{ {
return INTERNAL_SDL_GL_LoadLibrary( byte* utf8Path = Utf8Encode(path);
UTF8_ToNative(path) int result = INTERNAL_SDL_GL_LoadLibrary(
utf8Path
); );
Marshal.FreeHGlobal((IntPtr)utf8Path);
return result;
} }
/* IntPtr refers to a function pointer, proc to a const char* */ /* IntPtr refers to a function pointer, proc to a const char* */
@ -1675,13 +1780,15 @@ namespace SDL2
public static extern void SDL_GL_UnloadLibrary(); public static extern void SDL_GL_UnloadLibrary();
[DllImport(nativeLibName, EntryPoint = "SDL_GL_ExtensionSupported", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GL_ExtensionSupported", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_bool INTERNAL_SDL_GL_ExtensionSupported( private static extern unsafe SDL_bool INTERNAL_SDL_GL_ExtensionSupported(
byte[] extension byte* extension
); );
public static SDL_bool SDL_GL_ExtensionSupported(string extension) public static unsafe SDL_bool SDL_GL_ExtensionSupported(string extension)
{ {
int utf8ExtensionBufSize = Utf8SizeNullable(extension);
byte* utf8Extension = stackalloc byte[utf8ExtensionBufSize];
return INTERNAL_SDL_GL_ExtensionSupported( return INTERNAL_SDL_GL_ExtensionSupported(
UTF8_ToNative(extension) Utf8Encode(extension, utf8Extension, utf8ExtensionBufSize)
); );
} }
@ -1779,19 +1886,21 @@ namespace SDL2
/* IntPtr and userdata are void*, window is an SDL_Window* */ /* IntPtr and userdata are void*, window is an SDL_Window* */
[DllImport(nativeLibName, EntryPoint = "SDL_SetWindowData", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_SetWindowData", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_SDL_SetWindowData( private static extern unsafe IntPtr INTERNAL_SDL_SetWindowData(
IntPtr window, IntPtr window,
byte[] name, byte* name,
IntPtr userdata IntPtr userdata
); );
public static IntPtr SDL_SetWindowData( public static unsafe IntPtr SDL_SetWindowData(
IntPtr window, IntPtr window,
string name, string name,
IntPtr userdata IntPtr userdata
) { ) {
int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
return INTERNAL_SDL_SetWindowData( return INTERNAL_SDL_SetWindowData(
window, window,
UTF8_ToNative(name), Utf8Encode(name, utf8Name, utf8NameBufSize),
userdata userdata
); );
} }
@ -1896,17 +2005,19 @@ namespace SDL2
/* window refers to an SDL_Window* */ /* window refers to an SDL_Window* */
[DllImport(nativeLibName, EntryPoint = "SDL_SetWindowTitle", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_SetWindowTitle", CallingConvention = CallingConvention.Cdecl)]
private static extern void INTERNAL_SDL_SetWindowTitle( private static extern unsafe void INTERNAL_SDL_SetWindowTitle(
IntPtr window, IntPtr window,
byte[] title byte* title
); );
public static void SDL_SetWindowTitle( public static unsafe void SDL_SetWindowTitle(
IntPtr window, IntPtr window,
string title string title
) { ) {
int utf8TitleBufSize = Utf8Size(title);
byte* utf8Title = stackalloc byte[utf8TitleBufSize];
INTERNAL_SDL_SetWindowTitle( INTERNAL_SDL_SetWindowTitle(
window, window,
UTF8_ToNative(title) Utf8Encode(title, utf8Title, utf8TitleBufSize)
); );
} }
@ -1927,13 +2038,15 @@ namespace SDL2
); );
[DllImport(nativeLibName, EntryPoint = "SDL_VideoInit", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_VideoInit", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_SDL_VideoInit( private static extern unsafe int INTERNAL_SDL_VideoInit(
byte[] driver_name byte* driver_name
); );
public static int SDL_VideoInit(string driver_name) public static unsafe int SDL_VideoInit(string driver_name)
{ {
int utf8DriverNameBufSize = Utf8Size(driver_name);
byte* utf8DriverName = stackalloc byte[utf8DriverNameBufSize];
return INTERNAL_SDL_VideoInit( return INTERNAL_SDL_VideoInit(
UTF8_ToNative(driver_name) Utf8Encode(driver_name, utf8DriverName, utf8DriverNameBufSize)
); );
} }
@ -2011,14 +2124,17 @@ namespace SDL2
/* Only available in 2.0.6 or higher. */ /* Only available in 2.0.6 or higher. */
[DllImport(nativeLibName, EntryPoint = "SDL_Vulkan_LoadLibrary", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_Vulkan_LoadLibrary", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_SDL_Vulkan_LoadLibrary( private static extern unsafe int INTERNAL_SDL_Vulkan_LoadLibrary(
byte[] path byte* path
); );
public static int SDL_Vulkan_LoadLibrary(string path) public static unsafe int SDL_Vulkan_LoadLibrary(string path)
{ {
return INTERNAL_SDL_Vulkan_LoadLibrary( byte* utf8Path = Utf8Encode(path);
UTF8_ToNative(path) int result = INTERNAL_SDL_Vulkan_LoadLibrary(
utf8Path
); );
Marshal.FreeHGlobal((IntPtr)utf8Path);
return result;
} }
/* Only available in 2.0.6 or higher. */ /* Only available in 2.0.6 or higher. */
@ -4196,15 +4312,18 @@ namespace SDL2
} }
[DllImport(nativeLibName, EntryPoint = "SDL_SetClipboardText", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_SetClipboardText", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_SDL_SetClipboardText( private static extern unsafe int INTERNAL_SDL_SetClipboardText(
byte[] text byte* text
); );
public static int SDL_SetClipboardText( public static unsafe int SDL_SetClipboardText(
string text string text
) { ) {
return INTERNAL_SDL_SetClipboardText( byte* utf8Text = Utf8Encode(text);
UTF8_ToNative(text) int result = INTERNAL_SDL_SetClipboardText(
utf8Text
); );
Marshal.FreeHGlobal((IntPtr)utf8Text);
return result;
} }
#endregion #endregion
@ -5529,13 +5648,15 @@ namespace SDL2
/* Get a scancode from a human-readable name */ /* Get a scancode from a human-readable name */
[DllImport(nativeLibName, EntryPoint = "SDL_GetScancodeFromName", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GetScancodeFromName", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_Scancode INTERNAL_SDL_GetScancodeFromName( private static extern unsafe SDL_Scancode INTERNAL_SDL_GetScancodeFromName(
byte[] name byte* name
); );
public static SDL_Scancode SDL_GetScancodeFromName(string name) public static unsafe SDL_Scancode SDL_GetScancodeFromName(string name)
{ {
int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
return INTERNAL_SDL_GetScancodeFromName( return INTERNAL_SDL_GetScancodeFromName(
UTF8_ToNative(name) Utf8Encode(name, utf8Name, utf8NameBufSize)
); );
} }
@ -5549,12 +5670,16 @@ namespace SDL2
/* Get a key code from a human-readable name */ /* Get a key code from a human-readable name */
[DllImport(nativeLibName, EntryPoint = "SDL_GetKeyFromName", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GetKeyFromName", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_Keycode INTERNAL_SDL_GetKeyFromName( private static extern unsafe SDL_Keycode INTERNAL_SDL_GetKeyFromName(
byte[] name byte* name
); );
public static SDL_Keycode SDL_GetKeyFromName(string name) public static unsafe SDL_Keycode SDL_GetKeyFromName(string name)
{ {
return INTERNAL_SDL_GetKeyFromName(UTF8_ToNative(name)); int utf8NameBufSize = Utf8Size(name);
byte* utf8Name = stackalloc byte[utf8NameBufSize];
return INTERNAL_SDL_GetKeyFromName(
Utf8Encode(name, utf8Name, utf8NameBufSize)
);
} }
/* Start accepting Unicode text input events, show keyboard */ /* Start accepting Unicode text input events, show keyboard */
@ -5975,13 +6100,15 @@ namespace SDL2
); );
[DllImport(nativeLibName, EntryPoint = "SDL_JoystickGetGUIDFromString", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_JoystickGetGUIDFromString", CallingConvention = CallingConvention.Cdecl)]
private static extern Guid INTERNAL_SDL_JoystickGetGUIDFromString( private static extern unsafe Guid INTERNAL_SDL_JoystickGetGUIDFromString(
byte[] pchGUID byte* pchGUID
); );
public static Guid SDL_JoystickGetGUIDFromString(string pchGuid) public static unsafe Guid SDL_JoystickGetGUIDFromString(string pchGuid)
{ {
int utf8PchGuidBufSize = Utf8Size(pchGuid);
byte* utf8PchGuid = stackalloc byte[utf8PchGuidBufSize];
return INTERNAL_SDL_JoystickGetGUIDFromString( return INTERNAL_SDL_JoystickGetGUIDFromString(
UTF8_ToNative(pchGuid) Utf8Encode(pchGuid, utf8PchGuid, utf8PchGuidBufSize)
); );
} }
@ -6169,15 +6296,18 @@ namespace SDL2
} }
[DllImport(nativeLibName, EntryPoint = "SDL_GameControllerAddMapping", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GameControllerAddMapping", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_SDL_GameControllerAddMapping( private static extern unsafe int INTERNAL_SDL_GameControllerAddMapping(
byte[] mappingString byte* mappingString
); );
public static int SDL_GameControllerAddMapping( public static unsafe int SDL_GameControllerAddMapping(
string mappingString string mappingString
) { ) {
return INTERNAL_SDL_GameControllerAddMapping( byte* utf8MappingString = Utf8Encode(mappingString);
UTF8_ToNative(mappingString) int result = INTERNAL_SDL_GameControllerAddMapping(
utf8MappingString
); );
Marshal.FreeHGlobal((IntPtr)utf8MappingString);
return result;
} }
/* Only available in 2.0.6 or higher. */ /* Only available in 2.0.6 or higher. */
@ -6324,14 +6454,16 @@ namespace SDL2
public static extern void SDL_GameControllerUpdate(); public static extern void SDL_GameControllerUpdate();
[DllImport(nativeLibName, EntryPoint = "SDL_GameControllerGetAxisFromString", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GameControllerGetAxisFromString", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_GameControllerAxis INTERNAL_SDL_GameControllerGetAxisFromString( private static extern unsafe SDL_GameControllerAxis INTERNAL_SDL_GameControllerGetAxisFromString(
byte[] pchString byte* pchString
); );
public static SDL_GameControllerAxis SDL_GameControllerGetAxisFromString( public static unsafe SDL_GameControllerAxis SDL_GameControllerGetAxisFromString(
string pchString string pchString
) { ) {
int utf8PchStringBufSize = Utf8Size(pchString);
byte* utf8PchString = stackalloc byte[utf8PchStringBufSize];
return INTERNAL_SDL_GameControllerGetAxisFromString( return INTERNAL_SDL_GameControllerGetAxisFromString(
UTF8_ToNative(pchString) Utf8Encode(pchString, utf8PchString, utf8PchStringBufSize)
); );
} }
@ -6379,14 +6511,16 @@ namespace SDL2
); );
[DllImport(nativeLibName, EntryPoint = "SDL_GameControllerGetButtonFromString", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GameControllerGetButtonFromString", CallingConvention = CallingConvention.Cdecl)]
private static extern SDL_GameControllerButton INTERNAL_SDL_GameControllerGetButtonFromString( private static extern unsafe SDL_GameControllerButton INTERNAL_SDL_GameControllerGetButtonFromString(
byte[] pchString byte* pchString
); );
public static SDL_GameControllerButton SDL_GameControllerGetButtonFromString( public static unsafe SDL_GameControllerButton SDL_GameControllerGetButtonFromString(
string pchString string pchString
) { ) {
int utf8PchStringBufSize = Utf8Size(pchString);
byte* utf8PchString = stackalloc byte[utf8PchStringBufSize];
return INTERNAL_SDL_GameControllerGetButtonFromString( return INTERNAL_SDL_GameControllerGetButtonFromString(
UTF8_ToNative(pchString) Utf8Encode(pchString, utf8PchString, utf8PchStringBufSize)
); );
} }
@ -7010,13 +7144,15 @@ namespace SDL2
); );
[DllImport(nativeLibName, EntryPoint = "SDL_AudioInit", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_AudioInit", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_SDL_AudioInit( private static extern unsafe int INTERNAL_SDL_AudioInit(
byte[] driver_name byte* driver_name
); );
public static int SDL_AudioInit(string driver_name) public static unsafe int SDL_AudioInit(string driver_name)
{ {
int utf8DriverNameBufSize = Utf8Size(driver_name);
byte* utf8DriverName = stackalloc byte[utf8DriverNameBufSize];
return INTERNAL_SDL_AudioInit( return INTERNAL_SDL_AudioInit(
UTF8_ToNative(driver_name) Utf8Encode(driver_name, utf8DriverName, utf8DriverNameBufSize)
); );
} }
@ -7154,22 +7290,24 @@ namespace SDL2
/* uint refers to an SDL_AudioDeviceID */ /* uint refers to an SDL_AudioDeviceID */
[DllImport(nativeLibName, EntryPoint = "SDL_OpenAudioDevice", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_OpenAudioDevice", CallingConvention = CallingConvention.Cdecl)]
private static extern uint INTERNAL_SDL_OpenAudioDevice( private static extern unsafe uint INTERNAL_SDL_OpenAudioDevice(
byte[] device, byte* device,
int iscapture, int iscapture,
ref SDL_AudioSpec desired, ref SDL_AudioSpec desired,
out SDL_AudioSpec obtained, out SDL_AudioSpec obtained,
int allowed_changes int allowed_changes
); );
public static uint SDL_OpenAudioDevice( public static unsafe uint SDL_OpenAudioDevice(
string device, string device,
int iscapture, int iscapture,
ref SDL_AudioSpec desired, ref SDL_AudioSpec desired,
out SDL_AudioSpec obtained, out SDL_AudioSpec obtained,
int allowed_changes int allowed_changes
) { ) {
int utf8DeviceBufSize = Utf8Size(device);
byte* utf8Device = stackalloc byte[utf8DeviceBufSize];
return INTERNAL_SDL_OpenAudioDevice( return INTERNAL_SDL_OpenAudioDevice(
UTF8_ToNative(device), Utf8Encode(device, utf8Device, utf8DeviceBufSize),
iscapture, iscapture,
ref desired, ref desired,
out obtained, out obtained,
@ -7580,16 +7718,22 @@ namespace SDL2
/* Only available in 2.0.1 or higher. */ /* Only available in 2.0.1 or higher. */
[DllImport(nativeLibName, EntryPoint = "SDL_GetPrefPath", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "SDL_GetPrefPath", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_SDL_GetPrefPath( private static extern unsafe IntPtr INTERNAL_SDL_GetPrefPath(
byte[] org, byte* org,
byte[] app byte* app
); );
public static string SDL_GetPrefPath(string org, string app) public static unsafe string SDL_GetPrefPath(string org, string app)
{ {
int utf8OrgBufSize = Utf8SizeNullable(org);
byte* utf8Org = stackalloc byte[utf8OrgBufSize];
int utf8AppBufSize = Utf8SizeNullable(app);
byte* utf8App = stackalloc byte[utf8AppBufSize];
return UTF8_ToManaged( return UTF8_ToManaged(
INTERNAL_SDL_GetPrefPath( INTERNAL_SDL_GetPrefPath(
UTF8_ToNative(org), Utf8EncodeNullable(org, utf8Org, utf8OrgBufSize),
UTF8_ToNative(app) Utf8EncodeNullable(app, utf8App, utf8AppBufSize)
), ),
true true
); );

View file

@ -89,12 +89,17 @@ namespace SDL2
/* IntPtr refers to an SDL_Surface* */ /* IntPtr refers to an SDL_Surface* */
[DllImport(nativeLibName, EntryPoint = "IMG_Load", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "IMG_Load", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_IMG_Load( private static extern unsafe IntPtr INTERNAL_IMG_Load(
byte[] file byte* file
); );
public static IntPtr IMG_Load(string file) public static unsafe IntPtr IMG_Load(string file)
{ {
return INTERNAL_IMG_Load(SDL.UTF8_ToNative(file)); byte* utf8File = SDL.Utf8Encode(file);
IntPtr handle = INTERNAL_IMG_Load(
utf8File
);
Marshal.FreeHGlobal((IntPtr)utf8File);
return handle;
} }
/* src refers to an SDL_RWops*, IntPtr to an SDL_Surface* */ /* src refers to an SDL_RWops*, IntPtr to an SDL_Surface* */
@ -108,37 +113,42 @@ namespace SDL2
/* src refers to an SDL_RWops*, IntPtr to an SDL_Surface* */ /* src refers to an SDL_RWops*, IntPtr to an SDL_Surface* */
/* THIS IS A PUBLIC RWops FUNCTION! */ /* THIS IS A PUBLIC RWops FUNCTION! */
[DllImport(nativeLibName, EntryPoint = "IMG_LoadTyped_RW", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "IMG_LoadTyped_RW", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_IMG_LoadTyped_RW( private static extern unsafe IntPtr INTERNAL_IMG_LoadTyped_RW(
IntPtr src, IntPtr src,
int freesrc, int freesrc,
byte[] type byte* type
); );
public static IntPtr IMG_LoadTyped_RW( public static unsafe IntPtr IMG_LoadTyped_RW(
IntPtr src, IntPtr src,
int freesrc, int freesrc,
string type string type
) { ) {
int utf8TypeBufSize = SDL.Utf8Size(type);
byte* utf8Type = stackalloc byte[utf8TypeBufSize];
return INTERNAL_IMG_LoadTyped_RW( return INTERNAL_IMG_LoadTyped_RW(
src, src,
freesrc, freesrc,
SDL.UTF8_ToNative(type) SDL.Utf8Encode(type, utf8Type, utf8TypeBufSize)
); );
} }
/* IntPtr refers to an SDL_Texture*, renderer to an SDL_Renderer* */ /* IntPtr refers to an SDL_Texture*, renderer to an SDL_Renderer* */
[DllImport(nativeLibName, EntryPoint = "IMG_LoadTexture", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "IMG_LoadTexture", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_IMG_LoadTexture( private static extern unsafe IntPtr INTERNAL_IMG_LoadTexture(
IntPtr renderer, IntPtr renderer,
byte[] file byte* file
); );
public static IntPtr IMG_LoadTexture( public static unsafe IntPtr IMG_LoadTexture(
IntPtr renderer, IntPtr renderer,
string file string file
) { ) {
return INTERNAL_IMG_LoadTexture( byte* utf8File = SDL.Utf8Encode(file);
IntPtr handle = INTERNAL_IMG_LoadTexture(
renderer, renderer,
SDL.UTF8_ToNative(file) utf8File
); );
Marshal.FreeHGlobal((IntPtr)utf8File);
return handle;
} }
/* renderer refers to an SDL_Renderer*. /* renderer refers to an SDL_Renderer*.
@ -159,24 +169,27 @@ namespace SDL2
*/ */
/* THIS IS A PUBLIC RWops FUNCTION! */ /* THIS IS A PUBLIC RWops FUNCTION! */
[DllImport(nativeLibName, EntryPoint = "IMG_LoadTextureTyped_RW", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "IMG_LoadTextureTyped_RW", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr INTERNAL_IMG_LoadTextureTyped_RW( private static extern unsafe IntPtr INTERNAL_IMG_LoadTextureTyped_RW(
IntPtr renderer, IntPtr renderer,
IntPtr src, IntPtr src,
int freesrc, int freesrc,
byte[] type byte* type
); );
public static IntPtr IMG_LoadTextureTyped_RW( public static unsafe IntPtr IMG_LoadTextureTyped_RW(
IntPtr renderer, IntPtr renderer,
IntPtr src, IntPtr src,
int freesrc, int freesrc,
string type string type
) { ) {
return INTERNAL_IMG_LoadTextureTyped_RW( byte* utf8Type = SDL.Utf8Encode(type);
IntPtr handle = INTERNAL_IMG_LoadTextureTyped_RW(
renderer, renderer,
src, src,
freesrc, freesrc,
SDL.UTF8_ToNative(type) utf8Type
); );
Marshal.FreeHGlobal((IntPtr)utf8Type);
return handle;
} }
/* IntPtr refers to an SDL_Surface* */ /* IntPtr refers to an SDL_Surface* */
@ -188,16 +201,19 @@ namespace SDL2
/* surface refers to an SDL_Surface* */ /* surface refers to an SDL_Surface* */
[DllImport(nativeLibName, EntryPoint = "IMG_SavePNG", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "IMG_SavePNG", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_IMG_SavePNG( private static extern unsafe int INTERNAL_IMG_SavePNG(
IntPtr surface, IntPtr surface,
byte[] file byte* file
); );
public static int IMG_SavePNG(IntPtr surface, string file) public static unsafe int IMG_SavePNG(IntPtr surface, string file)
{ {
return INTERNAL_IMG_SavePNG( byte* utf8File = SDL.Utf8Encode(file);
int result = INTERNAL_IMG_SavePNG(
surface, surface,
SDL.UTF8_ToNative(file) utf8File
); );
Marshal.FreeHGlobal((IntPtr)utf8File);
return result;
} }
/* surface refers to an SDL_Surface*, dst to an SDL_RWops* */ /* surface refers to an SDL_Surface*, dst to an SDL_RWops* */
@ -211,18 +227,21 @@ namespace SDL2
/* surface refers to an SDL_Surface* */ /* surface refers to an SDL_Surface* */
[DllImport(nativeLibName, EntryPoint = "IMG_SaveJPG", CallingConvention = CallingConvention.Cdecl)] [DllImport(nativeLibName, EntryPoint = "IMG_SaveJPG", CallingConvention = CallingConvention.Cdecl)]
private static extern int INTERNAL_IMG_SaveJPG( private static extern unsafe int INTERNAL_IMG_SaveJPG(
IntPtr surface, IntPtr surface,
byte[] file, byte* file,
int quality int quality
); );
public static int IMG_SaveJPG(IntPtr surface, string file, int quality) public static unsafe int IMG_SaveJPG(IntPtr surface, string file, int quality)
{ {
return INTERNAL_IMG_SaveJPG( byte* utf8File = SDL.Utf8Encode(file);
int result = INTERNAL_IMG_SaveJPG(
surface, surface,
SDL.UTF8_ToNative(file), utf8File,
quality quality
); );
Marshal.FreeHGlobal((IntPtr)utf8File);
return result;
} }
/* surface refers to an SDL_Surface*, dst to an SDL_RWops* */ /* surface refers to an SDL_Surface*, dst to an SDL_RWops* */