public void GenerateDelegateConverterImplementation(AST.Delegate type) { const string dName = "___del"; Strata = ApiStrata.ABI; var typeRef = TypeRef(type, false); var typeRefABI = TypeRef(type, true); Line($"HRESULT DW{type.ShortId}::AbiFunc({DeclParameters(type.GetABIParametersCpp(true))})"); Block(() => { Line($"auto {dName} = runtime_cast<DW{type.ShortId}>(__i_);"); Line($"if (!{dName}) return E_FAIL;"); Spacer(); ABIWrapperParameterValidation(type); ABIWrappedCall(type, null, $"{dName}->Func"); }); Spacer(); Strata = ApiStrata.Normal; Line("template<>"); Line($"{TypeRef(type, false)} ABIUtil<{typeRef}>::FromABI(void* fptr, IObject* ctx)"); //Line($"Delegate<{Signature(type, false)}> DW{type.ShortId}::Lookup({TypeRef(type)} fptr, IObject* ctx)"); Block(() => { Line( $@"if (fptr == &DW{type.ShortId}::AbiFunc) {{ auto wrapper = runtime_cast<DW{type.ShortId}>(ctx); if (!wrapper) throw Exception(""Unexpected context type for delegate translation""); return wrapper->Func; }} return [fn = ({typeRefABI})fptr, cp = com_ptr<IObject>(ctx)]({DeclParameters(type.Parameters)})"); if (!type.Return.IsVoid) { Code(" -> {0} ", VariableType(type.Return, AST.VariableContext.Return)); } Block(() => { CallToABIMethodBody(type.Rename("fn"), "cp.Get()"); }, ";"); }); Spacer(); Line("template<>"); Line("ABIOf<{0}> ABIUtil<{0}>::ToABI(const {0}& x)", typeRef); Block(() => { Line($"ABIOf<{typeRef}> x_abi;"); Line($"x_abi.Fn = &DW{type.ShortId}::AbiFunc;"); Line($"x_abi.Ctx = DW{type.ShortId}::GetWrapper(x);"); Line("return x_abi;"); }); }
public void DefineDelegate(AST.Delegate type, string name = null) { if (name == null) { name = type.Name; } Namespace(type.Namespace, false, () => { WriteXmlDocumentation(type.XmlDoc); Line($"{(Strata == ApiStrata.ABI ? "internal" : "public")} delegate {TypeRef(type.Return)} {name}({DeclParameters(type.Parameters)});"); }); }
public void GenerateDelegateConverterDeclaration(AST.Delegate type) { var name = "DW" + type.ShortId; Strata = ApiStrata.ABI; var dSig = Signature(type, false); Line( $@"class comid(""{type.Id}"") {name} : public ComObject<{name}, Object>, public ABI::DelegateWrapperBase<{name}, {dSig}> {{ public:"); Indent++; Line($"DW{type.ShortId}(const Delegate<{dSig}>& d) : DBase(d) {{ }}"); Line($"static Delegate<{dSig}> Lookup({TypeRef(type)} fptr, IObject* ctx);"); Line($"static HRESULT __stdcall AbiFunc({DeclParameters(type.GetABIParametersCpp(true))});"); Indent--; Line("};"); Spacer(); }
public void DefineDelegateWrapper(AST.Delegate type) { Strata = ApiStrata.ABI; Line($"public class D{type.ShortId} : Gluon.D_Base"); Block(() => { var argstring = DeclParameters(type.GetABIParametersCs(true)); Line( $@"private NativeDel _abi; internal static readonly NativeDel FnDel = new NativeDel(Fn); public static readonly IntPtr FnPtr = Marshal.GetFunctionPointerForDelegate(FnDel); internal delegate HResult NativeDel({argstring});"); Line(); if (TargetMono) { Line("[AOT.MonoPInvokeCallback(typeof(NativeDel))]"); } Line($"private static HResult Fn({argstring})"); Block(() => { Strata = ApiStrata.Normal; Line($"var del = ((GCHandle)Marshal.GetObjectForIUnknown(__i_)).Target as {TypeRef(type)};"); Line(); Line("try"); Block(() => { WriteWrappedCall(true, "del", type.Return, null, type.Parameters.ToArray()); }); Line("catch (Exception e)"); Block(() => { foreach (var arg in type.GetABIParametersCs(true).Where(a => a.IsOut)) { Line($"{arg.Name} = default({TypeRef(arg, true)});"); } Line("return GluonObject.ExceptionToHResult(e);"); }); }); Line( @"private D{1}(IntPtr fn, IntPtr ctx) : base(ctx) {{ _abi = (NativeDel)Marshal.GetDelegateForFunctionPointer(fn, typeof(NativeDel)); }} public static {0} Wrap(IntPtr fn, IntPtr ctx) {{ if (fn == IntPtr.Zero) return null; else if (fn == D{1}.FnPtr) return ((GCHandle)Marshal.GetObjectForIUnknown(ctx)).Target as {0}; else return new D{1}(fn, ctx).Call; }} public static DelegateBlob Unwrap({0} x) {{ return x == null ? new DelegateBlob(IntPtr.Zero, IntPtr.Zero) : new DelegateBlob(FnPtr, Marshal.GetIUnknownForObject(GCHandle.Alloc(x))); }} public static DelegateBlob[] ToABI_Array({0}[] x) {{ if (x == null) return null; var r = new DelegateBlob[x.Length]; for (int i = 0; i < x.Length; i++) r[i] = Unwrap(x[i]); return r; }} public static {0}[] FromABI_Array(DelegateBlob[] x) {{ if (x == null) return null; var r = new {0}[x.Length]; for (int i = 0; i < x.Length; i++) r[i] = Wrap(x[i].Fn, x[i].Ctx); return r; }} ", TypeRef(type), type.ShortId); Line($"private {TypeRef(type.Return)} Call({DeclParameters(type.Parameters)})"); Block(() => { Strata = ApiStrata.Normal; WriteWrappedCall(false, "(int)_abi", type.Return, new AST.Parameter() { Type = BasicTypes.IntPtr, Name = "_ctx" }, type.Parameters.ToArray()); Strata = ApiStrata.ABI; }); }); }