1using System.CodeDom.Compiler;
4using Microsoft.CodeAnalysis;
8public class MethodExporter(IMethodSymbol symbol) : IExporter
10 private string GetMangling()
12 return $
"__interop_{symbol.GetUnmanagedMethodName()}";
15 public void GenerateUnmanagedCode(IndentedTextWriter source, IndentedTextWriter header)
18 var argsPack =
new ParameterPack(symbol);
19 argsPack.GenerateUnmanagedStub(header);
23 var sb =
new StringBuilder();
24 sb.Append(symbol.ReturnType.GetNativeName()).Append(
' ');
25 var namespaceOffset = sb.Length;
27 sb.Append(symbol.GetUnmanagedMethodName()).Append(
'(');
28 for (var i = 0; i < symbol.Parameters.Length; i++)
30 var parameter = symbol.Parameters[i];
33 sb.Append($
"{parameter.Type.GetNativeName()} {parameter.Name}");
37 header.WriteLine(sb.ToString());
40 sb.Insert(namespaceOffset, $
"{symbol.ContainingType.GetNativeName()}::");
41 sb.Remove(sb.Length - 1, 1);
42 source.WriteLine(sb.ToString());
44 source.WriteLine(
"{");
50 sb.Append($
"{argsPack.Name} __argpack(");
54 if (symbol.Parameters.Any())
57 for (var i = 0; i < symbol.Parameters.Length; i++)
59 var parameter = symbol.Parameters[i];
62 sb.Append($
"{parameter.Name}");
65 source.WriteLine(sb.ToString());
68 source.WriteLine(
"int (*fp)(void*, std::int32_t) = reinterpret_cast<decltype(fp)>(g_dhost->LoadMethod(");
70 source.WriteLine($
"\"{symbol.ContainingType.GetAssemblyQualifiedName()}\",");
71 source.WriteLine($
"\"{GetMangling()}\"));");
75 source.WriteLine(
"fp(&__argpack, sizeof(__argpack));");
76 if (symbol.Name ==
".ctor")
77 source.WriteLine(
"__this = __argpack.__this;");
78 if (!symbol.ReturnsVoid)
79 source.WriteLine(
"return __argpack.__return;");
82 source.WriteLine(
"}");
85 public void GenerateManagedCode(IndentedTextWriter builder)
87 var argsPack =
new ParameterPack(symbol);
88 argsPack.GenerateManagedStub(builder);
91 builder.WriteLine(
"[System.Runtime.InteropServices.UnmanagedCallersOnly]");
92 builder.WriteLine($
"public static unsafe int {GetMangling()}({argsPack.Name}* argpack, int size)");
93 builder.WriteLine(
"{");
96 if (symbol.Name ==
".ctor")
98 var args =
string.Join(
", ", symbol.Parameters.Select(parameter => $
"argpack->{parameter.Name}"));
99 builder.WriteLine($
"var obj = new {symbol.ContainingType.Name}({args})");
100 builder.WriteLine(
"var handle = System.Runtime.InteropServices.GCHandle.Alloc(obj, System.Runtime.InteropServices.GCHandleType.Pinned);");
101 builder.WriteLine(
"argpack->__this = handle.AddrOfPinnedObject();");
105 var args =
string.Join(
", ", symbol.Parameters.Select(parameter => $
"argpack->{parameter.Name}"));
106 builder.WriteLine(
"var handle = System.Runtime.InteropServices.GCHandle.FromIntPtr(argpack->__this);");
107 builder.WriteLine($
"argpack->__return = (({symbol.ContainingType.Name})handle.Target).{symbol.Name}({args});");
110 builder.WriteLine(
"return 0;");
113 builder.WriteLine(
"}");