@@ -123,10 +123,10 @@ public Metadata(double[] value)
123123
124124 }
125125
126- public Metadata ( string [ ] value )
127- : this ( NativeMethods . BNCreateMetadataStringListData ( value , ( ulong ) value . Length ) , true )
126+ public Metadata ( string [ ] value )
127+ : this ( Metadata . rawCreateMetadataStringList ( value ) , true )
128128 {
129-
129+
130130 }
131131
132132 public Metadata ( Metadata [ ] value )
@@ -225,12 +225,21 @@ private static IntPtr rawCreateMetadataDict(IDictionary<string,Metadata> dict)
225225 {
226226 handles . Add ( item . DangerousGetHandle ( ) ) ;
227227 }
228-
229- return NativeMethods . BNCreateMetadataValueStore (
230- dict . Keys . ToArray ( ) ,
231- handles . ToArray ( ) ,
232- ( ulong ) handles . Count
233- ) ;
228+
229+ string [ ] keys = dict . Keys . ToArray ( ) ;
230+
231+ // Keys are a UTF-8 char** block (see rawCreateMetadataStringList); the
232+ // core copies them, so freeing after the call is safe.
233+ using ( ScopedAllocator allocator = new ScopedAllocator ( ) )
234+ {
235+ IntPtr keyBlock = allocator . AllocUtf8StringArray ( keys ) ;
236+
237+ return NativeMethods . BNCreateMetadataValueStore (
238+ keyBlock ,
239+ handles . ToArray ( ) ,
240+ ( ulong ) handles . Count
241+ ) ;
242+ }
234243 }
235244
236245 public static Metadata FromBoolArray ( bool [ ] values )
@@ -264,9 +273,27 @@ public static Metadata FromDoubleArray(double[] values)
264273 public static Metadata FromStringArray ( string [ ] values )
265274 {
266275 return Metadata . MustTakeHandle (
267- NativeMethods . BNCreateMetadataStringListData ( values , ( ulong ) values . Length )
276+ Metadata . rawCreateMetadataStringList ( values )
268277 ) ;
269278 }
279+
280+ // BN stores string lists as UTF-8 char** blocks. .NET cannot marshal a
281+ // string[] element as UTF-8 via [MarshalAs] (LPUTF8Str is rejected for an
282+ // array subtype), so build the char** block by hand. The core copies the
283+ // strings, so freeing the block after the call (ScopedAllocator dispose)
284+ // is safe.
285+ private static IntPtr rawCreateMetadataStringList ( string [ ] values )
286+ {
287+ using ( ScopedAllocator allocator = new ScopedAllocator ( ) )
288+ {
289+ IntPtr block = allocator . AllocUtf8StringArray ( values ) ;
290+
291+ return NativeMethods . BNCreateMetadataStringListData (
292+ block ,
293+ ( ulong ) values . Length
294+ ) ;
295+ }
296+ }
270297
271298 internal static Metadata ? NewFromHandle ( IntPtr handle )
272299 {
@@ -425,7 +452,7 @@ public string[] ToStringList()
425452 out ulong arrayLength
426453 ) ;
427454
428- string [ ] values = UnsafeUtils . ReadAnsiStringArray ( arrayPointer , arrayLength ) ;
455+ string [ ] values = UnsafeUtils . ReadUtf8StringArray ( arrayPointer , arrayLength ) ;
429456
430457 if ( arrayPointer != IntPtr . Zero )
431458 {
@@ -730,9 +757,9 @@ public bool SetValue(string key , double[] values)
730757 public bool SetValue ( string key , string [ ] values )
731758 {
732759 return NativeMethods . BNMetadataSetValueForKey (
733- this . handle ,
734- key ,
735- NativeMethods . BNCreateMetadataStringListData ( values , ( ulong ) values . Length )
760+ this . handle ,
761+ key ,
762+ Metadata . rawCreateMetadataStringList ( values )
736763 ) ;
737764 }
738765
0 commit comments