Skip to content

Commit 7c0c71f

Browse files
authored
Add Pinvoke support on coreclr (#6542)
1 parent 0d72794 commit 7c0c71f

1 file changed

Lines changed: 42 additions & 7 deletions

File tree

src/absil/ilreflect.fs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,20 +1489,46 @@ let emitParameter cenv emEnv (defineParameter: int * ParameterAttributes * strin
14891489
//----------------------------------------------------------------------------
14901490
// buildMethodPass2
14911491
//----------------------------------------------------------------------------
1492-
1492+
1493+
#if !FX_RESHAPED_REFEMIT || NETCOREAPP3_0
1494+
1495+
let enablePInvoke = true
1496+
1497+
#else
1498+
1499+
// We currently build targeting netcoreapp2_1, and will continue to do so through this VS cycle
1500+
// but we can run on Netcoreapp3.0 so ... use reflection to invoke the api, when we are executing on netcoreapp3.0
1501+
let definePInvokeMethod =
1502+
typeof<TypeBuilder>.GetMethod("DefinePInvokeMethod", [|
1503+
typeof<string>;
1504+
typeof<string>;
1505+
typeof<string>;
1506+
typeof<System.Reflection.MethodAttributes>;
1507+
typeof<System.Reflection.CallingConventions>;
1508+
typeof<Type>;
1509+
typeof<Type[]>;
1510+
typeof<Type[]>;
1511+
typeof<Type[]>;
1512+
typeof<Type[][]>;
1513+
typeof<Type[][]>;
1514+
typeof<System.Runtime.InteropServices.CallingConvention>;
1515+
typeof<System.Runtime.InteropServices.CharSet> |])
1516+
1517+
let enablePInvoke = definePInvokeMethod <> null
1518+
#endif
1519+
14931520
let rec buildMethodPass2 cenv tref (typB: TypeBuilder) emEnv (mdef: ILMethodDef) =
14941521
let attrs = mdef.Attributes
14951522
let implflags = mdef.ImplAttributes
14961523
let cconv = convCallConv mdef.CallingConv
1497-
let mref = mkRefToILMethod (tref, mdef)
1524+
let mref = mkRefToILMethod (tref, mdef)
14981525
let emEnv =
1499-
if mdef.IsEntryPoint && isNil mdef.ParameterTypes then
1526+
if mdef.IsEntryPoint && isNil mdef.ParameterTypes then
15001527
envAddEntryPt emEnv (typB, mdef.Name)
15011528
else
15021529
emEnv
15031530
match mdef.Body.Contents with
1504-
#if !FX_RESHAPED_REFEMIT
1505-
| MethodBody.PInvoke p ->
1531+
| MethodBody.PInvoke p when enablePInvoke ->
15061532
let argtys = convTypesToArray cenv emEnv mdef.ParameterTypes
15071533
let rty = convType cenv emEnv mdef.Return.Type
15081534

@@ -1524,10 +1550,19 @@ let rec buildMethodPass2 cenv tref (typB: TypeBuilder) emEnv (mdef: ILMethodDef)
15241550
(* p.CharBestFit *)
15251551
(* p.NoMangle *)
15261552

1527-
let methB = typB.DefinePInvokeMethod(mdef.Name, p.Where.Name, p.Name, attrs, cconv, rty, null, null, argtys, null, null, pcc, pcs)
1553+
#if !FX_RESHAPED_REFEMIT || NETCOREAPP3_0
1554+
// DefinePInvokeMethod was removed in early versions of coreclr, it was added back in NETCORE_APP3_0.
1555+
// It has always been available in the desktop framework
1556+
let methB = typB.DefinePInvokeMethod(mdef.Name, p.Where.Name, p.Name, attrs, cconv, rty, null, null, argtys, null, null, pcc, pcs)
1557+
#else
1558+
// We currently build targeting netcoreapp2_1, and will continue to do so through this VS cycle
1559+
// but we can run on Netcoreapp3.0 so ... use reflection to invoke the api, when we are executing on netcoreapp3.0
1560+
let methB =
1561+
System.Diagnostics.Debug.Assert(definePInvokeMethod <> null, "Runtime does not have DefinePInvokeMethod") // Absolutely can't happen
1562+
definePInvokeMethod.Invoke(typB, [| mdef.Name; p.Where.Name; p.Name; attrs; cconv; rty; null; null; argtys; null; null; pcc; pcs |]) :?> MethodBuilder
1563+
#endif
15281564
methB.SetImplementationFlagsAndLog implflags
15291565
envBindMethodRef emEnv mref methB
1530-
#endif
15311566

15321567
| _ ->
15331568
match mdef.Name with

0 commit comments

Comments
 (0)