@@ -30,6 +30,7 @@ public CSharpMarshalContext(Driver driver)
30
30
31
31
public TextGenerator ArgumentPrefix { get ; private set ; }
32
32
public TextGenerator Cleanup { get ; private set ; }
33
+ public bool HasFixedBlock { get ; set ; }
33
34
}
34
35
35
36
public abstract class CSharpMarshalPrinter : MarshalPrinter
@@ -390,28 +391,43 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
390
391
if ( ! VisitType ( array , quals ) )
391
392
return false ;
392
393
393
- Class @class ;
394
394
switch ( array . SizeType )
395
395
{
396
396
case ArrayType . ArraySize . Constant :
397
- var supportBefore = Context . SupportBefore ;
398
- supportBefore . WriteLine ( "if ({0} != null)" , Context . ArgName ) ;
399
- supportBefore . WriteStartBraceIndent ( ) ;
400
- if ( array . Type . Desugar ( ) . TryGetClass ( out @class ) && @class . IsRefType )
397
+ if ( string . IsNullOrEmpty ( Context . ReturnVarName ) )
401
398
{
402
- supportBefore . WriteLine ( "if (value.Length != {0})" , array . Size ) ;
403
- supportBefore . WriteLineIndent ( "throw new ArgumentOutOfRangeException(\" {0}\" , \" The provided array's dimensions doesn't match the required size.\" );" ,
404
- Context . Parameter . Name ) ;
399
+ Context . SupportBefore . WriteLine ( "if ({0} == null || {0}.Length != {1})" , Context . Parameter . Name , array . Size ) ;
400
+ ThrowArgumentOutOfRangeException ( ) ;
401
+ const string ptr = "__ptr" ;
402
+ Context . SupportBefore . WriteLine ( "fixed ({0}* {1} = {2})" , array . Type , ptr , Context . Parameter . Name ) ;
403
+ Context . SupportBefore . WriteStartBraceIndent ( ) ;
404
+ Context . Return . Write ( "new global::System.IntPtr({0})" , ptr ) ;
405
+ CSharpContext . HasFixedBlock = true ;
405
406
}
406
- supportBefore . WriteLine ( "for (int i = 0; i < {0}; i++)" , array . Size ) ;
407
- if ( @class != null && @class . IsRefType )
408
- supportBefore . WriteLineIndent ( "{0}[i * sizeof({2}.Internal)] = *((byte*)({2}.Internal*){1}[i].__Instance);" ,
409
- Context . ReturnVarName , Context . ArgName , array . Type ) ;
410
407
else
411
- supportBefore . WriteLineIndent ( "{0}[i] = {1}[i]{2};" ,
412
- Context . ReturnVarName , Context . ArgName ,
413
- array . Type . IsPointerToPrimitiveType ( PrimitiveType . Void ) ? ".ToPointer()" : string . Empty ) ;
414
- supportBefore . WriteCloseBraceIndent ( ) ;
408
+ {
409
+ var supportBefore = Context . SupportBefore ;
410
+ supportBefore . WriteLine ( "if ({0} != null)" , Context . ArgName ) ;
411
+ supportBefore . WriteStartBraceIndent ( ) ;
412
+ Class @class ;
413
+ if ( array . Type . Desugar ( ) . TryGetClass ( out @class ) && @class . IsRefType )
414
+ {
415
+ supportBefore . WriteLine ( "if (value.Length != {0})" , array . Size ) ;
416
+ ThrowArgumentOutOfRangeException ( ) ;
417
+ }
418
+ supportBefore . WriteLine ( "for (int i = 0; i < {0}; i++)" , array . Size ) ;
419
+ if ( @class != null && @class . IsRefType )
420
+ supportBefore . WriteLineIndent (
421
+ "{0}[i * sizeof({2}.Internal)] = *((byte*)({2}.Internal*){1}[i].__Instance);" ,
422
+ Context . ReturnVarName , Context . ArgName , array . Type ) ;
423
+ else
424
+ supportBefore . WriteLineIndent ( "{0}[i] = {1}[i]{2};" ,
425
+ Context . ReturnVarName , Context . ArgName ,
426
+ array . Type . IsPointerToPrimitiveType ( PrimitiveType . Void )
427
+ ? ".ToPointer()"
428
+ : string . Empty ) ;
429
+ supportBefore . WriteCloseBraceIndent ( ) ;
430
+ }
415
431
break ;
416
432
default :
417
433
Context . Return . Write ( "null" ) ;
@@ -420,6 +436,14 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
420
436
return true ;
421
437
}
422
438
439
+ private void ThrowArgumentOutOfRangeException ( )
440
+ {
441
+ Context . SupportBefore . WriteLineIndent (
442
+ "throw new ArgumentOutOfRangeException(\" {0}\" , " +
443
+ "\" The dimensions of the provided array don't match the required size.\" );" ,
444
+ Context . Parameter . Name ) ;
445
+ }
446
+
423
447
public bool VisitDelegateType ( FunctionType function , string type )
424
448
{
425
449
Context . Return . Write ( "{0} == null ? global::System.IntPtr.Zero : Marshal.GetFunctionPointerForDelegate({0})" ,
@@ -432,6 +456,17 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
432
456
if ( ! VisitType ( pointer , quals ) )
433
457
return false ;
434
458
459
+ if ( Context . Function != null && pointer . IsPrimitiveTypeConvertibleToRef ( ) )
460
+ {
461
+ string refParamPtr = string . Format ( "__refParamPtr{0}" , Context . ParameterIndex ) ;
462
+ Context . SupportBefore . WriteLine ( "fixed ({0} {1} = &{2})" ,
463
+ pointer , refParamPtr , Context . Parameter . Name ) ;
464
+ CSharpContext . HasFixedBlock = true ;
465
+ Context . SupportBefore . WriteStartBraceIndent ( ) ;
466
+ Context . Return . Write ( refParamPtr ) ;
467
+ return true ;
468
+ }
469
+
435
470
var param = Context . Parameter ;
436
471
var isRefParam = param != null && ( param . IsInOut || param . IsOut ) ;
437
472
0 commit comments