@@ -214,8 +214,7 @@ private void SetupLogging(Action<ObsLogLevel, string> handler)
214214 {
215215 try
216216 {
217- // For now, just pass the format string - proper va_list handling is complex
218- var message = Marshal . PtrToStringUTF8 ( format ) ?? string . Empty ;
217+ var message = FormatLogMessage ( format , args ) ;
219218 handler ( ( ObsLogLevel ) level , message ) ;
220219 }
221220 catch
@@ -227,6 +226,36 @@ private void SetupLogging(Action<ObsLogLevel, string> handler)
227226 ObsCore . base_set_log_handler ( _logHandler , 0 ) ;
228227 }
229228
229+ private static string FormatLogMessage ( nint format , nint args )
230+ {
231+ if ( format == nint . Zero )
232+ return string . Empty ;
233+
234+ // Use vsnprintf to format the message with va_list arguments
235+ // First call with null buffer to get required size
236+ int size = NativeVsnprintf ( nint . Zero , 0 , format , args ) ;
237+ if ( size <= 0 )
238+ {
239+ // Fallback to just the format string if formatting fails
240+ return Marshal . PtrToStringUTF8 ( format ) ?? string . Empty ;
241+ }
242+
243+ // Allocate buffer and format the message
244+ var buffer = Marshal . AllocHGlobal ( size + 1 ) ;
245+ try
246+ {
247+ NativeVsnprintf ( buffer , ( nuint ) ( size + 1 ) , format , args ) ;
248+ return Marshal . PtrToStringUTF8 ( buffer ) ?? string . Empty ;
249+ }
250+ finally
251+ {
252+ Marshal . FreeHGlobal ( buffer ) ;
253+ }
254+ }
255+
256+ [ DllImport ( "msvcrt.dll" , EntryPoint = "vsnprintf" , CallingConvention = CallingConvention . Cdecl ) ]
257+ private static extern int NativeVsnprintf ( nint buffer , nuint size , nint format , nint args ) ;
258+
230259 [ SupportedOSPlatform ( "windows" ) ]
231260 private void InitializeComForWindows ( )
232261 {
0 commit comments