public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var matcher = Matcher.CType( new TupleCType(aNativeFunction.CurrentParameterType, aNativeFunction.NextParameterType)); if (!matcher.Match(new TupleCType( new PointerCType(new NamedCType("char")), new NamedCType("int") ))) { return false; } if (aNativeFunction.CurrentParameter.Name != "buffer") return false; if (aNativeFunction.NextParameter.Name != "buffer_size") return false; string parameterName = aNativeFunction.CurrentParameter.Name; string utf8StringName = "utf8_"+parameterName; aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, utf8StringName + ".IntPtr"); aAssembler.AddPInvokeParameter(new CSharpType("int"), aNativeFunction.NextParameter.Name, utf8StringName + ".BufferLength"); aAssembler.SetManagedReturn(new CSharpType("string")); aAssembler.InsertAtTop( "string returnValue;"); aAssembler.InsertBeforeCall("using (Utf8String " + utf8StringName + " = SpotifyMarshalling.AllocBuffer(256))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.InsertAfterCall("returnValue = " + utf8StringName + ".Value;"); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aAssembler.InsertAtEnd("return returnValue;"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var firstArgType = aNativeFunction.CurrentParameterType; var secondArgType = aNativeFunction.NextParameterType; bool secondArgIsInt = secondArgType.MatchToPattern(new NamedCType("int")).IsMatch; if (!secondArgIsInt) { return false; } bool firstArgIsPointer = firstArgType is PointerCType; if (!firstArgIsPointer) { return false; } var derefOnceType = firstArgType.ChildType; bool firstArgIsPointerToPointer = derefOnceType is PointerCType; if (!firstArgIsPointerToPointer) { return false; } var derefTwiceType = derefOnceType.ChildType; bool firstArgIsPointerToPointerToNamedType = derefTwiceType is NamedCType; if (!firstArgIsPointerToPointerToNamedType) { return false; } var elementType = (NamedCType)derefTwiceType; bool arrayIsMutable = !derefOnceType.Qualifiers.Contains("const"); string arg1name = aNativeFunction.CurrentParameter.Name; string arg2name = aNativeFunction.NextParameter.Name; if (arg2name != "num_" + arg1name) { return false; } string className; if (!iHandlesToClassNames.TryGetValue(elementType.Name, out className)) { return false; } // Finally, we are sure that this is an array of handles. // Now we need to marshal the cursed thing! string paramName = aNativeFunction.CurrentParameter.Name; aAssembler.AddPInvokeParameter( new CSharpType("IntPtr"), paramName, "array_" + paramName + ".IntPtr"); aAssembler.AddPInvokeParameter( new CSharpType("int"), "num_" + paramName, "array_" + paramName + ".Length"); aAssembler.AddManagedParameter( paramName, new CSharpType(className + "[]")); aAssembler.InsertBeforeCall("using (var array_" + paramName + " = SpotifyMarshalling.ArrayToNativeArray(" + paramName + ", x=>x._handle))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); if (arrayIsMutable) { // Unless we pass in a 'handle * const *', the function might have changed // the content of the array, so copy it back. aAssembler.InsertAfterCall("array_" + paramName + ".CopyTo(" + paramName + ", ptr => ptr == IntPtr.Zero ? null : new " + className + "(ptr));"); } aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall( "}"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var matcher = Matcher.CType(new TupleCType( aNativeFunction.CurrentParameterType, aNativeFunction.NextParameterType)); if (!matcher.Match(new TupleCType( new PointerCType(new VariableCType("element-type")), new NamedCType("int")))) { return false; } var elementType = matcher.BoundVariables["element-type"] as NamedCType; if (elementType == null) { return false; } string arg1name = aNativeFunction.CurrentParameter.Name; string arg2name = aNativeFunction.NextParameter.Name; if (arg2name != "num_" + arg1name) { return false; } string managedType; switch (elementType.Name) { case "int": managedType = "int"; break; default: return false; } // Finally, we are sure that this is an array of handles. // Now we need to marshal the cursed thing! string paramName = aNativeFunction.CurrentParameter.Name; aAssembler.AddPInvokeParameter( new CSharpType("IntPtr"), paramName, "array_" + paramName + ".IntPtr"); aAssembler.AddPInvokeParameter( new CSharpType("int"), "num_" + paramName, "array_" + paramName + ".Length"); aAssembler.AddManagedParameter( paramName, new CSharpType(managedType + "[]")); aAssembler.InsertBeforeCall("using (var array_" + paramName + " = SpotifyMarshalling.ArrayToNativeArray(" + paramName + "))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.InsertAfterCall( "Array.Copy(array_"+paramName+".Value(), "+paramName+", "+paramName+".Length);"); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { if (!aNativeFunction.CurrentParameterType.MatchToPattern( new PointerCType(new NamedCType("char"))).IsMatch) { return(false); } if (-1 != Matcher.CType(aNativeFunction.CurrentParameterType).FirstMatch( new NamedCType("size_t"), new NamedCType("int") )) { return(false); } if (!aNativeFunction.ReturnType.MatchToPattern( new NamedCType("int")).IsMatch) { return(false); } if (aNativeFunction.CurrentParameterIndex != aNativeFunction.ParameterCount - 2) { return(false); } string lengthNativeType = ((NamedCType)aNativeFunction.NextParameterType).Name; string lengthManagedType = lengthNativeType == "size_t" ? "UIntPtr" : "int"; string parameterName = aNativeFunction.CurrentParameter.Name; string utf8StringName = "utf8_" + parameterName; aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, utf8StringName + ".IntPtr"); aAssembler.AddPInvokeParameter(new CSharpType(lengthManagedType), aNativeFunction.NextParameter.Name, "(" + lengthManagedType + ")(" + utf8StringName + ".BufferLength)"); aAssembler.SetPInvokeReturn(new CSharpType("int"), "stringLength_" + parameterName); aAssembler.SetManagedReturn(new CSharpType("string")); aAssembler.InsertAtTop("string returnValue;"); aAssembler.InsertAtTop("int stringLength_" + parameterName + " = 256;"); aAssembler.InsertBeforeCall("using (Utf8String " + utf8StringName + " = SpotifyMarshalling.AllocBuffer(stringLength_" + parameterName + "))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.InsertPreCall("stringLength_" + parameterName); aAssembler.InsertBeforeCall(utf8StringName + ".ReallocIfSmaller(stringLength_" + parameterName + " + 1);"); aAssembler.InsertAfterCall("returnValue = " + utf8StringName + ".GetString(stringLength_" + parameterName + ");"); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aAssembler.InsertAtEnd("return returnValue;"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeReturn(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { if (!aNativeFunction.CurrentParameterType.MatchToPattern( new PointerCType(new NamedCType("char"))).IsMatch) { return false; } if (-1 != Matcher.CType(aNativeFunction.CurrentParameterType).FirstMatch( new NamedCType("size_t"), new NamedCType("int") )) { return false; } if (!aNativeFunction.ReturnType.MatchToPattern( new NamedCType("int")).IsMatch) { return false; } if (aNativeFunction.CurrentParameterIndex != aNativeFunction.ParameterCount - 2) { return false; } string lengthNativeType = ((NamedCType)aNativeFunction.NextParameterType).Name; string lengthManagedType = lengthNativeType == "size_t" ? "UIntPtr" : "int"; string parameterName = aNativeFunction.CurrentParameter.Name; string utf8StringName = "utf8_"+parameterName; aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, utf8StringName + ".IntPtr"); aAssembler.AddPInvokeParameter(new CSharpType(lengthManagedType), aNativeFunction.NextParameter.Name, "(" + lengthManagedType + ")(" + utf8StringName + ".BufferLength)"); aAssembler.SetPInvokeReturn(new CSharpType("int"), "stringLength_"+parameterName); aAssembler.SetManagedReturn(new CSharpType("string")); aAssembler.InsertAtTop( "string returnValue;"); aAssembler.InsertAtTop("int stringLength_" + parameterName + " = 256;"); aAssembler.InsertBeforeCall("using (Utf8String " + utf8StringName + " = SpotifyMarshalling.AllocBuffer(stringLength_" + parameterName + "))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.InsertPreCall("stringLength_" + parameterName); aAssembler.InsertBeforeCall(utf8StringName + ".ReallocIfSmaller(stringLength_" + parameterName + " + 1);"); aAssembler.InsertAfterCall("returnValue = " + utf8StringName + ".GetString(stringLength_" + parameterName + ");"); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aAssembler.InsertAtEnd("return returnValue;"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeReturn(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var pointerType = aNativeFunction.CurrentParameterType as PointerCType; if (pointerType == null) { return(false); } var namedType = pointerType.BaseType as NamedCType; if (namedType == null) { return(false); } string className; if (!iHandlesToClassNames.TryGetValue(namedType.Name, out className)) { return(false); } aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, aNativeFunction.CurrentParameter.Name + "._handle"); aAssembler.AddManagedParameter(aNativeFunction.CurrentParameter.Name, new CSharpType(className)); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { NamedCType nativeType = aNativeFunction.CurrentParameterType as NamedCType; if (nativeType == null) return false; CSharpType pinvokeArgType; CSharpType managedArgType; switch (nativeType.Name) { case "bool": pinvokeArgType = new CSharpType("bool"){ Attributes = { "MarshalAs(UnmanagedType.I1)" } }; managedArgType = new CSharpType("bool"); break; case "int": pinvokeArgType = managedArgType = new CSharpType("int"); break; case "size_t": pinvokeArgType = managedArgType = new CSharpType("UIntPtr"); break; default: string managedEnumName; if (!iEnumNativeToManagedMappings.TryGetValue(nativeType.Name, out managedEnumName)) { return false; } pinvokeArgType = managedArgType = new CSharpType(managedEnumName); break; } aAssembler.AddPInvokeParameter(pinvokeArgType, aNativeFunction.CurrentParameter.Name, aNativeFunction.CurrentParameter.Name); aAssembler.AddManagedParameter(aNativeFunction.CurrentParameter.Name, managedArgType); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var pointerType = aNativeFunction.CurrentParameterType as PointerCType; if (pointerType == null) { return(false); } var namedType = pointerType.BaseType as NamedCType; if (namedType == null) { return(false); } switch (namedType.Name) { case "void": break; default: return(false); } aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, null); aAssembler.SuppressManagedWrapper(); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var pointerType = aNativeFunction.CurrentParameterType as PointerCType; if (pointerType == null) { return(false); } var namedType = pointerType.BaseType as NamedCType; if (namedType == null) { return(false); } string structName; if (!iHandlesToStructNames.TryGetValue(namedType.Name, out structName)) { return(false); } aAssembler.AddPInvokeParameter(new CSharpType(structName) { IsRef = true }, aNativeFunction.CurrentParameter.Name, null); aAssembler.SuppressManagedWrapper(); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var matcher = Matcher.CType( new TupleCType(aNativeFunction.CurrentParameterType, aNativeFunction.NextParameterType)); if (!matcher.Match(new TupleCType( new PointerCType(new NamedCType("char")), new NamedCType("int") ))) { return(false); } if (aNativeFunction.CurrentParameter.Name != "buffer") { return(false); } if (aNativeFunction.NextParameter.Name != "buffer_size") { return(false); } string parameterName = aNativeFunction.CurrentParameter.Name; string utf8StringName = "utf8_" + parameterName; aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, utf8StringName + ".IntPtr"); aAssembler.AddPInvokeParameter(new CSharpType("int"), aNativeFunction.NextParameter.Name, utf8StringName + ".BufferLength"); aAssembler.SetManagedReturn(new CSharpType("string")); aAssembler.InsertAtTop("string returnValue;"); aAssembler.InsertBeforeCall("using (Utf8String " + utf8StringName + " = SpotifyMarshalling.AllocBuffer(256))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.InsertAfterCall("returnValue = " + utf8StringName + ".Value;"); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aAssembler.InsertAtEnd("return returnValue;"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var pointerType = aNativeFunction.CurrentParameterType as PointerCType; if (pointerType == null) return false; var namedType = pointerType.BaseType as NamedCType; if (namedType == null) return false; // Accept anything. aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, null); aAssembler.SuppressManagedWrapper(); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { if (aNativeFunction.CurrentParameterIndex != 0) { return(false); } if (!aNativeFunction.CurrentParameterType.MatchToPattern(new PointerCType(new NamedCType(HandleType))).IsMatch) { return(false); } aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, "this._handle"); aAssembler.IsStatic = false; aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var pointerType = aNativeFunction.CurrentParameterType as PointerCType; if (pointerType == null) return false; var namedType = pointerType.BaseType as NamedCType; if (namedType == null) return false; string structName; if (!iHandlesToStructNames.TryGetValue(namedType.Name, out structName)) { return false; } aAssembler.AddPInvokeParameter(new CSharpType(structName) { IsRef = true }, aNativeFunction.CurrentParameter.Name, null); aAssembler.SuppressManagedWrapper(); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var pointerType = aNativeFunction.CurrentParameterType as PointerCType; if (pointerType == null) return false; var namedType = pointerType.BaseType as NamedCType; if (namedType == null) return false; string className; if (!iHandlesToClassNames.TryGetValue(namedType.Name, out className)) { return false; } aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, aNativeFunction.CurrentParameter.Name + "._handle"); aAssembler.AddManagedParameter(aNativeFunction.CurrentParameter.Name, new CSharpType(className)); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var matcher = Matcher.CType(aNativeFunction.CurrentParameterType); if (!matcher.Match(new PointerCType(new NamedCType("char") { Qualifiers = { "const" } }))) { return false; } string utf8StringName = "utf8_" + aNativeFunction.CurrentParameter.Name; aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, utf8StringName + ".IntPtr"); aAssembler.AddManagedParameter(aNativeFunction.CurrentParameter.Name, new CSharpType("string")); aAssembler.InsertBeforeCall("using (Utf8String " + utf8StringName + " = SpotifyMarshalling.StringToUtf8(" + aNativeFunction.CurrentParameter.Name + "))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { PointerCType pointer1Type = aNativeFunction.CurrentParameterType as PointerCType; if (pointer1Type == null) return false; PointerCType pointer2Type = pointer1Type.BaseType as PointerCType; if (pointer2Type == null) return false; NamedCType nativeType = pointer2Type.BaseType as NamedCType; if (nativeType == null) return false; if (!iHandleNames.Contains(nativeType.Name)) return false; aAssembler.AddPInvokeParameter( new CSharpType("IntPtr") { IsRef = true }, aNativeFunction.CurrentParameter.Name, null); aAssembler.SuppressManagedWrapper(); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { NamedCType nativeType = aNativeFunction.CurrentParameterType as NamedCType; if (nativeType == null) { return(false); } CSharpType pinvokeArgType; CSharpType managedArgType; switch (nativeType.Name) { case "bool": pinvokeArgType = new CSharpType("bool") { Attributes = { "MarshalAs(UnmanagedType.I1)" } }; managedArgType = new CSharpType("bool"); break; case "int": pinvokeArgType = managedArgType = new CSharpType("int"); break; case "size_t": pinvokeArgType = managedArgType = new CSharpType("UIntPtr"); break; default: string managedEnumName; if (!iEnumNativeToManagedMappings.TryGetValue(nativeType.Name, out managedEnumName)) { return(false); } pinvokeArgType = managedArgType = new CSharpType(managedEnumName); break; } aAssembler.AddPInvokeParameter(pinvokeArgType, aNativeFunction.CurrentParameter.Name, aNativeFunction.CurrentParameter.Name); aAssembler.AddManagedParameter(aNativeFunction.CurrentParameter.Name, managedArgType); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var arrayType = aNativeFunction.CurrentParameterType as ArrayCType; if (arrayType == null) return false; var namedType = arrayType.BaseType as NamedCType; if (namedType == null) return false; switch (namedType.Name) { case "byte": break; default: return false; } aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, null); aAssembler.SuppressManagedWrapper(); aNativeFunction.ConsumeArgument(); return true; }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var matcher = Matcher.CType(aNativeFunction.CurrentParameterType); if (!matcher.Match(new PointerCType(new NamedCType("char") { Qualifiers = { "const" } }))) { return(false); } string utf8StringName = "utf8_" + aNativeFunction.CurrentParameter.Name; aAssembler.AddPInvokeParameter(new CSharpType("IntPtr"), aNativeFunction.CurrentParameter.Name, utf8StringName + ".IntPtr"); aAssembler.AddManagedParameter(aNativeFunction.CurrentParameter.Name, new CSharpType("string")); aAssembler.InsertBeforeCall("using (Utf8String " + utf8StringName + " = SpotifyMarshalling.StringToUtf8(" + aNativeFunction.CurrentParameter.Name + "))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { PointerCType pointer1Type = aNativeFunction.CurrentParameterType as PointerCType; if (pointer1Type == null) { return(false); } PointerCType pointer2Type = pointer1Type.BaseType as PointerCType; if (pointer2Type == null) { return(false); } NamedCType nativeType = pointer2Type.BaseType as NamedCType; if (nativeType == null) { return(false); } if (!iHandleNames.Contains(nativeType.Name)) { return(false); } aAssembler.AddPInvokeParameter( new CSharpType("IntPtr") { IsRef = true }, aNativeFunction.CurrentParameter.Name, null); aAssembler.SuppressManagedWrapper(); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var matcher = Matcher.CType(new TupleCType( aNativeFunction.CurrentParameterType, aNativeFunction.NextParameterType)); if (!matcher.Match(new TupleCType( new PointerCType(new VariableCType("element-type")), new NamedCType("int")))) { return(false); } var elementType = matcher.BoundVariables["element-type"] as NamedCType; if (elementType == null) { return(false); } string arg1name = aNativeFunction.CurrentParameter.Name; string arg2name = aNativeFunction.NextParameter.Name; if (arg2name != "num_" + arg1name) { return(false); } string managedType; switch (elementType.Name) { case "int": managedType = "int"; break; default: return(false); } // Finally, we are sure that this is an array of handles. // Now we need to marshal the cursed thing! string paramName = aNativeFunction.CurrentParameter.Name; aAssembler.AddPInvokeParameter( new CSharpType("IntPtr"), paramName, "array_" + paramName + ".IntPtr"); aAssembler.AddPInvokeParameter( new CSharpType("int"), "num_" + paramName, "array_" + paramName + ".Length"); aAssembler.AddManagedParameter( paramName, new CSharpType(managedType + "[]")); aAssembler.InsertBeforeCall("using (var array_" + paramName + " = SpotifyMarshalling.ArrayToNativeArray(" + paramName + "))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); aAssembler.InsertAfterCall("Array.Copy(array_" + paramName + ".Value(), " + paramName + ", " + paramName + ".Length);"); aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); return(true); }
public bool Apply(IFunctionSpecificationAnalyser aNativeFunction, IFunctionAssembler aAssembler) { var firstArgType = aNativeFunction.CurrentParameterType; var secondArgType = aNativeFunction.NextParameterType; bool secondArgIsInt = secondArgType.MatchToPattern(new NamedCType("int")).IsMatch; if (!secondArgIsInt) { return(false); } bool firstArgIsPointer = firstArgType is PointerCType; if (!firstArgIsPointer) { return(false); } var derefOnceType = firstArgType.ChildType; bool firstArgIsPointerToPointer = derefOnceType is PointerCType; if (!firstArgIsPointerToPointer) { return(false); } var derefTwiceType = derefOnceType.ChildType; bool firstArgIsPointerToPointerToNamedType = derefTwiceType is NamedCType; if (!firstArgIsPointerToPointerToNamedType) { return(false); } var elementType = (NamedCType)derefTwiceType; bool arrayIsMutable = !derefOnceType.Qualifiers.Contains("const"); string arg1name = aNativeFunction.CurrentParameter.Name; string arg2name = aNativeFunction.NextParameter.Name; if (arg2name != "num_" + arg1name) { return(false); } string className; if (!iHandlesToClassNames.TryGetValue(elementType.Name, out className)) { return(false); } // Finally, we are sure that this is an array of handles. // Now we need to marshal the cursed thing! string paramName = aNativeFunction.CurrentParameter.Name; aAssembler.AddPInvokeParameter( new CSharpType("IntPtr"), paramName, "array_" + paramName + ".IntPtr"); aAssembler.AddPInvokeParameter( new CSharpType("int"), "num_" + paramName, "array_" + paramName + ".Length"); aAssembler.AddManagedParameter( paramName, new CSharpType(className + "[]")); aAssembler.InsertBeforeCall("using (var array_" + paramName + " = SpotifyMarshalling.ArrayToNativeArray(" + paramName + ", x=>x._handle))"); aAssembler.InsertBeforeCall("{"); aAssembler.IncreaseIndent(); if (arrayIsMutable) { // Unless we pass in a 'handle * const *', the function might have changed // the content of the array, so copy it back. aAssembler.InsertAfterCall("array_" + paramName + ".CopyTo(" + paramName + ", ptr => ptr == IntPtr.Zero ? null : new " + className + "(ptr));"); } aAssembler.DecreaseIndent(); aAssembler.InsertAfterCall("}"); aNativeFunction.ConsumeArgument(); aNativeFunction.ConsumeArgument(); return(true); }