diff --git a/src/Generator/Generators/C/CCodeGenerator.cs b/src/Generator/Generators/C/CCodeGenerator.cs index 879d8d11..4fea70b9 100644 --- a/src/Generator/Generators/C/CCodeGenerator.cs +++ b/src/Generator/Generators/C/CCodeGenerator.cs @@ -152,7 +152,7 @@ namespace CppSharp.Generators.C if (IsCLIGenerator) { if (@enum.Modifiers.HasFlag(Enumeration.EnumModifiers.Flags)) - WriteLine("[System::Flags]"); + WriteLine("[::System::Flags]"); // A nested class cannot have an assembly access specifier as part // of its declaration. diff --git a/src/Generator/Generators/C/CppMarshal.cs b/src/Generator/Generators/C/CppMarshal.cs index b0632b43..d62ce2f5 100644 --- a/src/Generator/Generators/C/CppMarshal.cs +++ b/src/Generator/Generators/C/CppMarshal.cs @@ -272,7 +272,7 @@ namespace CppSharp.Generators.Cpp Context.Return.Write($"({instance} == nullptr) ? nullptr : {MemoryAllocOperator} "); Context.Return.Write($"{QualifiedIdentifier(@class)}("); - Context.Return.Write($"(::{@class.QualifiedOriginalName}*)"); + Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)"); Context.Return.Write($"{instance})"); } @@ -409,7 +409,7 @@ namespace CppSharp.Generators.Cpp Context.Parameter.Usage == ParameterUsage.InOut; Context.ArgumentPrefix.Write("&"); - Context.Return.Write($"(::{@enum.QualifiedOriginalName}){0}{Context.Parameter.Name}", + Context.Return.Write($"(enum ::{@enum.QualifiedOriginalName}){0}{Context.Parameter.Name}", isRef ? string.Empty : "*"); return true; } @@ -511,7 +511,7 @@ namespace CppSharp.Generators.Cpp PrimitiveType primitive; if (decl.Type.IsPrimitiveType(out primitive)) { - Context.Return.Write($"(::{typedef.Declaration.QualifiedOriginalName})"); + Context.Return.Write($"(typedef ::{typedef.Declaration.QualifiedOriginalName})"); } return decl.Type.Visit(this); @@ -588,7 +588,7 @@ namespace CppSharp.Generators.Cpp && method.Conversion == MethodConversionKind.FunctionToInstanceMethod && Context.ParameterIndex == 0) { - Context.Return.Write($"(::{@class.QualifiedOriginalName}*)"); + Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)"); Context.Return.Write(Helpers.InstanceIdentifier); return; } @@ -596,7 +596,7 @@ namespace CppSharp.Generators.Cpp var paramType = Context.Parameter.Type.Desugar(); var isPointer = paramType.SkipPointerRefs().IsPointer(); var deref = isPointer ? "->" : "."; - var instance = $"(::{@class.QualifiedOriginalName}*)" + + var instance = $"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)" + $"{Context.Parameter.Name}{deref}{Helpers.InstanceIdentifier}"; if (isPointer) @@ -654,7 +654,7 @@ namespace CppSharp.Generators.Cpp public override bool VisitEnumDecl(Enumeration @enum) { - Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName, + Context.Return.Write("(enum ::{0}){1}", @enum.QualifiedOriginalName, Context.Parameter.Name); return true; } diff --git a/src/Generator/Generators/C/CppSources.cs b/src/Generator/Generators/C/CppSources.cs index 7f145bde..03b0bba5 100644 --- a/src/Generator/Generators/C/CppSources.cs +++ b/src/Generator/Generators/C/CppSources.cs @@ -294,7 +294,7 @@ namespace CppSharp.Generators.Cpp { Write($"{QualifiedIdentifier(@class)}::{@class.Name}("); - var nativeType = $"::{@class.QualifiedOriginalName}*"; + var nativeType = $"{(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*"; //WriteLine($"{nativeType} {ClassCtorInstanceParamIdentifier})"); WriteLine(!withOwnNativeInstanceParam ? $"{nativeType} {ClassCtorInstanceParamIdentifier})" : $"{nativeType} {ClassCtorInstanceParamIdentifier}, bool ownNativeInstance)"); @@ -413,7 +413,8 @@ namespace CppSharp.Generators.Cpp PushBlock(BlockKind.ConstructorBody, @class); var @params = GenerateFunctionParamsMarshal(method.Parameters, method); - Write($"{Helpers.InstanceIdentifier} = new ::{method.Namespace.QualifiedOriginalName}("); + Write($@"{Helpers.InstanceIdentifier} = new {(@class.IsUnion ? "union" : "struct")} ::{ + method.Namespace.QualifiedOriginalName}("); GenerateFunctionParams(@params); WriteLine(");"); @@ -492,7 +493,7 @@ namespace CppSharp.Generators.Cpp var field = property?.Field; if (field != null) { - Write($"((::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->"); + Write($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->"); Write($"{field.OriginalName}"); var isGetter = property.GetMethod == method; @@ -510,7 +511,7 @@ namespace CppSharp.Generators.Cpp else { if (IsNativeMethod(function)) - Write($"((::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->"); + Write($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->"); Write($"{base.GetMethodIdentifier(function, TypePrinterContextKind.Native)}("); } diff --git a/src/Generator/Generators/CLI/CLIHeaders.cs b/src/Generator/Generators/CLI/CLIHeaders.cs index 8da7f37e..2c618d9d 100644 --- a/src/Generator/Generators/CLI/CLIHeaders.cs +++ b/src/Generator/Generators/CLI/CLIHeaders.cs @@ -262,10 +262,10 @@ namespace CppSharp.Generators.CLI GenerateDeclContext(@class); Unindent(); - var nativeType = string.Format("::{0}*", @class.QualifiedOriginalName); + string nativeType = $"{(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*"; if (CLIGenerator.ShouldGenerateClassNativeField(@class)) - GenerateClassNativeField(@class, nativeType); + GenerateClassNativeField(nativeType); GenerateClassConstructors(@class, nativeType); @@ -303,15 +303,15 @@ namespace CppSharp.Generators.CLI WriteLine("};"); } - public void GenerateClassNativeField(Class @class, string nativeType) + public void GenerateClassNativeField(string nativeType) { WriteLineIndent("property {0} NativePtr;", nativeType); Indent(); - WriteLine("property System::IntPtr {0}", Helpers.InstanceIdentifier); + WriteLine("property ::System::IntPtr {0}", Helpers.InstanceIdentifier); WriteOpenBraceAndIndent(); - WriteLine("virtual System::IntPtr get();"); - WriteLine("virtual void set(System::IntPtr instance);"); + WriteLine("virtual ::System::IntPtr get();"); + WriteLine("virtual void set(::System::IntPtr instance);"); UnindentAndWriteCloseBrace(); NewLine(); @@ -455,7 +455,7 @@ namespace CppSharp.Generators.CLI GenerateDeclarationCommon(field); if (@class.IsUnion) - WriteLine("[System::Runtime::InteropServices::FieldOffset({0})]", + WriteLine("[::System::Runtime::InteropServices::FieldOffset({0})]", @class.Layout.Fields.Single(f => f.FieldPtr == field.OriginalPtr).Offset); WriteLine("{0} {1};", field.Type, field.Name); @@ -575,8 +575,8 @@ namespace CppSharp.Generators.CLI public override void GenerateClassSpecifier(Class @class) { if (@class.IsUnion) - WriteLine("[System::Runtime::InteropServices::StructLayout({0})]", - "System::Runtime::InteropServices::LayoutKind::Explicit"); + WriteLine("[::System::Runtime::InteropServices::StructLayout({0})]", + "::System::Runtime::InteropServices::LayoutKind::Explicit"); // Nested types cannot have visibility modifiers in C++/CLI. var isTopLevel = @class.Namespace is TranslationUnit || @@ -760,8 +760,8 @@ namespace CppSharp.Generators.CLI : ((FunctionType)attributedType).CallingConvention; var interopCallConv = callingConvention.ToInteropCallConv(); if (interopCallConv != System.Runtime.InteropServices.CallingConvention.Winapi) - WriteLine("[System::Runtime::InteropServices::UnmanagedFunctionPointer" + - "(System::Runtime::InteropServices::CallingConvention::{0})] ", + WriteLine("[::System::Runtime::InteropServices::UnmanagedFunctionPointer" + + "(::System::Runtime::InteropServices::CallingConvention::{0})] ", interopCallConv); var visibility = !insideClass ? "public " : string.Empty; diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index bb9c9ab4..2fd9c19a 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -83,9 +83,9 @@ namespace CppSharp.Generators.CLI var delegateType = function.ToString(); Context.Return.Write("safe_cast<{0}>(", delegateType + "^"); - Context.Return.Write("System::Runtime::InteropServices::Marshal::"); + Context.Return.Write("::System::Runtime::InteropServices::Marshal::"); Context.Return.Write("GetDelegateForFunctionPointer("); - Context.Return.Write("System::IntPtr({0}), {1}::typeid))", Context.ReturnVarName, + Context.Return.Write("::System::IntPtr({0}), {1}::typeid))", Context.ReturnVarName, delegateType.TrimEnd('^')); return true; @@ -223,9 +223,9 @@ namespace CppSharp.Generators.CLI if (decl.Type.IsPointerTo(out function)) { Context.Return.Write($"{Context.ReturnVarName} == nullptr ? nullptr : safe_cast<{typedef}>("); - Context.Return.Write("System::Runtime::InteropServices::Marshal::"); + Context.Return.Write("::System::Runtime::InteropServices::Marshal::"); Context.Return.Write("GetDelegateForFunctionPointer("); - Context.Return.Write("IntPtr({0}), {1}::typeid))",Context.ReturnVarName, + Context.Return.Write("::System::IntPtr({0}), {1}::typeid))", Context.ReturnVarName, typedef.ToString().TrimEnd('^')); return true; } @@ -280,8 +280,7 @@ namespace CppSharp.Generators.CLI if (@class.IsRefType && needsCopy) { var name = Generator.GeneratedIdentifier(Context.ReturnVarName); - Context.Before.WriteLine("auto {0} = new ::{1}({2});", name, - @class.QualifiedOriginalName, Context.ReturnVarName); + Context.Before.WriteLine($"auto {name} = new {(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}({Context.ReturnVarName});"); instance = name; ownNativeInstance = true; @@ -306,7 +305,7 @@ namespace CppSharp.Generators.CLI instance); Context.Return.Write("::{0}(", QualifiedIdentifier(@class)); - Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); + Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)"); Context.Return.Write("{0}{1})", instance, ownNativeInstance ? ", true" : ""); } @@ -449,7 +448,7 @@ namespace CppSharp.Generators.CLI supportBefore.WriteLine($"if ({Context.Parameter.Name}->Length != {array.Size})"); supportBefore.WriteOpenBraceAndIndent(); - supportBefore.WriteLine($"throw gcnew System::InvalidOperationException(\"Source array size must equal destination array size.\");"); + supportBefore.WriteLine($"throw gcnew ::System::InvalidOperationException(\"Source array size must equal destination array size.\");"); supportBefore.UnindentAndWriteCloseBrace(); string nativeVal = string.Empty; @@ -494,7 +493,7 @@ namespace CppSharp.Generators.CLI var sb = new StringBuilder(); sb.AppendFormat("static_cast<{0}>(", type); - sb.Append("System::Runtime::InteropServices::Marshal::"); + sb.Append("::System::Runtime::InteropServices::Marshal::"); sb.Append("GetFunctionPointerForDelegate("); sb.AppendFormat("{0}).ToPointer())", Context.Parameter.Name); Context.Return.Write(sb.ToString()); @@ -529,7 +528,7 @@ namespace CppSharp.Generators.CLI ArgumentPrefix.Write("&"); } - Context.Return.Write("(::{0}){1}{2}", @enum.QualifiedOriginalName, + Context.Return.Write("(enum ::{0}){1}{2}", @enum.QualifiedOriginalName, isRef ? string.Empty : "*", Context.Parameter.Name); return true; } @@ -728,12 +727,12 @@ namespace CppSharp.Generators.CLI && method.Conversion == MethodConversionKind.FunctionToInstanceMethod && Context.ParameterIndex == 0) { - Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); + Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)"); Context.Return.Write("NativePtr"); return; } - Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); + Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)"); Context.Return.Write("{0}->NativePtr", Context.Parameter.Name); } @@ -858,7 +857,7 @@ namespace CppSharp.Generators.CLI public override bool VisitEnumDecl(Enumeration @enum) { - Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName, + Context.Return.Write("(enum ::{0}){1}", @enum.QualifiedOriginalName, Context.Parameter.Name); return true; } diff --git a/src/Generator/Generators/CLI/CLISources.cs b/src/Generator/Generators/CLI/CLISources.cs index ede93351..ccda869d 100644 --- a/src/Generator/Generators/CLI/CLISources.cs +++ b/src/Generator/Generators/CLI/CLISources.cs @@ -136,18 +136,18 @@ namespace CppSharp.Generators.CLI var qualifiedIdentifier = QualifiedIdentifier(@class); PushBlock(BlockKind.Method); - WriteLine("System::IntPtr {0}::{1}::get()", + WriteLine("::System::IntPtr {0}::{1}::get()", qualifiedIdentifier, Helpers.InstanceIdentifier); WriteOpenBraceAndIndent(); - WriteLine("return System::IntPtr(NativePtr);"); + WriteLine("return ::System::IntPtr(NativePtr);"); UnindentAndWriteCloseBrace(); PopBlock(NewLineKind.BeforeNextBlock); PushBlock(BlockKind.Method); - WriteLine("void {0}::{1}::set(System::IntPtr object)", + WriteLine("void {0}::{1}::set(::System::IntPtr object)", qualifiedIdentifier, Helpers.InstanceIdentifier); WriteOpenBraceAndIndent(); - var nativeType = $"::{@class.QualifiedOriginalName}*"; + var nativeType = $"{(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*"; WriteLine("NativePtr = ({0})object.ToPointer();", nativeType); UnindentAndWriteCloseBrace(); PopBlock(NewLineKind.BeforeNextBlock); @@ -260,7 +260,7 @@ namespace CppSharp.Generators.CLI WriteOpenBraceAndIndent(); WriteLine("auto __nativePtr = NativePtr;"); WriteLine("NativePtr = 0;"); - WriteLine("delete (::{0}*) __nativePtr;", @class.QualifiedOriginalName); + WriteLine($"delete ({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*) __nativePtr;", @class.QualifiedOriginalName); UnindentAndWriteCloseBrace(); } @@ -398,7 +398,7 @@ namespace CppSharp.Generators.CLI if (decl is Variable) variable = $"::{@class.QualifiedOriginalName}::{decl.OriginalName}"; else - variable = $"((::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}"; + variable = $"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}"; var ctx = new MarshalContext(Context, CurrentIndentation) { @@ -483,8 +483,10 @@ namespace CppSharp.Generators.CLI string variable; if (decl is Variable) variable = $"::{@class.QualifiedOriginalName}::{decl.OriginalName}"; + else if (CLIGenerator.ShouldGenerateClassNativeField(@class)) + variable = $"NativePtr->{decl.OriginalName}"; else - variable = $"((::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}"; + variable = $"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}"; var ctx = new MarshalContext(Context, CurrentIndentation) { @@ -543,12 +545,11 @@ namespace CppSharp.Generators.CLI WriteLine("auto _fptr = (void (*)({0}))Marshal::GetFunctionPointerForDelegate({1}Instance).ToPointer();", args, delegateName); - WriteLine("((::{0}*)NativePtr)->{1}.Connect(_fptr);", @class.QualifiedOriginalName, - @event.OriginalName); + WriteLine($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->{@event.OriginalName}.Connect(_fptr);"); UnindentAndWriteCloseBrace(); - WriteLine("_{0} = static_cast<{1}>(System::Delegate::Combine(_{0}, evt));", + WriteLine("_{0} = static_cast<{1}>(::System::Delegate::Combine(_{0}, evt));", @event.Name, @event.Type); UnindentAndWriteCloseBrace(); @@ -560,7 +561,7 @@ namespace CppSharp.Generators.CLI @event.Name, @event.Type); WriteOpenBraceAndIndent(); - WriteLine("_{0} = static_cast<{1}>(System::Delegate::Remove(_{0}, evt));", + WriteLine("_{0} = static_cast<{1}>(::System::Delegate::Remove(_{0}, evt));", @event.Name, @event.Type); UnindentAndWriteCloseBrace(); @@ -630,7 +631,7 @@ namespace CppSharp.Generators.CLI Write("{0}::{1}(", qualifiedIdentifier, @class.Name); - var nativeType = string.Format("::{0}*", @class.QualifiedOriginalName); + string nativeType = $"{(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*"; WriteLine(!withOwnNativeInstanceParam ? "{0} native)" : "{0} native, bool ownNativeInstance)", nativeType); var hasBase = GenerateClassConstructorBase(@class, null, withOwnNativeInstanceParam); @@ -784,7 +785,8 @@ namespace CppSharp.Generators.CLI if (!@class.IsAbstract) { var @params = GenerateFunctionParamsMarshal(method.Parameters, method); - Write("NativePtr = new ::{0}(", method.Namespace.QualifiedOriginalName); + Write($@"NativePtr = new {(@class.IsUnion ? "union" : "struct")} ::{ + @class.QualifiedOriginalName}("); GenerateFunctionParams(@params); WriteLine(");"); } @@ -867,8 +869,8 @@ namespace CppSharp.Generators.CLI names.Add(marshal.Context.Return); } - WriteLine("::{0} _native({1});", @class.QualifiedOriginalName, - string.Join(", ", names)); + WriteLine($@"{(@class.IsUnion ? "union" : "struct")} ::{ + @class.QualifiedOriginalName} _native({string.Join(", ", names)});"); GenerateValueTypeConstructorCallProperties(@class); } @@ -959,7 +961,7 @@ namespace CppSharp.Generators.CLI var isValueType = @class != null && @class.IsValueType; if (isValueType && !IsNativeFunctionOrStaticMethod(function)) { - WriteLine("auto {0} = ::{1}();", valueMarshalName, @class.QualifiedOriginalName); + WriteLine($"auto {valueMarshalName} = {(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}();"); var param = new Parameter { Name = "(*this)" , Namespace = function.Namespace }; var ctx = new MarshalContext(Context, CurrentIndentation) @@ -1018,7 +1020,7 @@ namespace CppSharp.Generators.CLI if (isValueType) Write($"{valueMarshalName}."); else if (IsNativeMethod(function)) - Write("((::{0}*)NativePtr)->", @class.QualifiedOriginalName); + Write($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->"); Write("{0}(", function.OriginalName); } @@ -1067,7 +1069,7 @@ namespace CppSharp.Generators.CLI { WriteLine("if ({0} == nullptr) return {1};", returnIdentifier, - isIntPtr ? "System::IntPtr()" : "nullptr"); + isIntPtr ? "::System::IntPtr()" : "nullptr"); } var ctx = new MarshalContext(Context, CurrentIndentation) @@ -1103,10 +1105,10 @@ namespace CppSharp.Generators.CLI foreach (var param in method.Parameters.Where( p => p.Type.IsPrimitiveType(PrimitiveType.Char))) { - WriteLine("if ({0} < System::Char::MinValue || {0} > System::SByte::MaxValue)", param.Name); + WriteLine("if ({0} < ::System::Char::MinValue || {0} > ::System::SByte::MaxValue)", param.Name); // C++/CLI can actually handle char -> sbyte in all case, this is for compatibility with the C# generator WriteLineIndent( - "throw gcnew System::OverflowException(\"{0} must be in the range {1} - {2}.\");", + "throw gcnew ::System::OverflowException(\"{0} must be in the range {1} - {2}.\");", param.Name, (int) char.MinValue, sbyte.MaxValue); } } diff --git a/src/Generator/Generators/CLI/CLITypePrinter.cs b/src/Generator/Generators/CLI/CLITypePrinter.cs index 8b1dca12..27af84f5 100644 --- a/src/Generator/Generators/CLI/CLITypePrinter.cs +++ b/src/Generator/Generators/CLI/CLITypePrinter.cs @@ -38,7 +38,7 @@ namespace CppSharp.Generators.CLI if (array.SizeType == ArrayType.ArraySize.Incomplete && array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) - return "System::String^"; + return VisitCILType(new CILType(typeof(string)), quals); return $"cli::array<{array.Type.Visit(this)}>^"; } @@ -75,9 +75,9 @@ namespace CppSharp.Generators.CLI var str = string.Empty; if(param.Usage == ParameterUsage.Out) - str += "[System::Runtime::InteropServices::Out] "; + str += "[::System::Runtime::InteropServices::Out] "; else if (param.Usage == ParameterUsage.InOut) - str += "[System::Runtime::InteropServices::In, System::Runtime::InteropServices::Out] "; + str += "[::System::Runtime::InteropServices::In, ::System::Runtime::InteropServices::Out] "; str += type; @@ -179,8 +179,8 @@ namespace CppSharp.Generators.CLI case PrimitiveType.Void: return "void"; case PrimitiveType.Char16: case PrimitiveType.Char32: - case PrimitiveType.WideChar: return "System::Char"; - case PrimitiveType.Char: return Options.MarshalCharAsManagedChar ? "System::Char" : "char"; + case PrimitiveType.WideChar: return "::System::Char"; + case PrimitiveType.Char: return Options.MarshalCharAsManagedChar ? "::System::Char" : "char"; case PrimitiveType.SChar: return "signed char"; case PrimitiveType.UChar: return "unsigned char"; case PrimitiveType.Short: return "short"; @@ -200,7 +200,7 @@ namespace CppSharp.Generators.CLI case PrimitiveType.IntPtr: return "IntPtr"; case PrimitiveType.UIntPtr: return "UIntPtr"; case PrimitiveType.Null: return "void*"; - case PrimitiveType.String: return "System::String"; + case PrimitiveType.String: return "::System::String"; } throw new NotSupportedException(); @@ -300,7 +300,7 @@ namespace CppSharp.Generators.CLI if (!type.Type.IsValueType) result += "^"; - return result; + return $"::{result}"; } public override TypePrinterResult VisitUnsupportedType(UnsupportedType type, TypeQualifiers quals) diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index 93a07c3a..4880cac5 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -375,7 +375,7 @@ namespace CppSharp.Generators.CSharp base.GenerateDeclarationCommon(decl); foreach (Attribute attribute in decl.Attributes) - WriteLine("[{0}({1})]", attribute.Type.FullName, attribute.Value); + WriteLine("[global::{0}({1})]", attribute.Type.FullName, attribute.Value); } #region Classes @@ -2365,7 +2365,7 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetOrCreateInst internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({TypePrinter.IntPtrType} native) {{ if (!NativeToManagedMap.TryGetValue(native, out var managed)) - throw new System.Exception(""No managed instance was found""); + throw new global::System.Exception(""No managed instance was found""); var result = ({printedClass})managed; if (result.{Helpers.OwnsNativeInstanceIdentifier}) result.SetupVTables(); @@ -3423,6 +3423,11 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty if (function.IsPure) return; + if (function.OriginalName == "system_do_it") + { + System.Diagnostics.Debugger.Break(); + } + PushBlock(BlockKind.InternalsClassMethod); var callConv = function.CallingConvention.ToInteropCallConv(); @@ -3555,7 +3560,7 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty { WriteLine($"var path = \"{path}\";"); WriteLine("var image = CppSharp.SymbolResolver.LoadImage(ref path);"); - WriteLine("if (image == IntPtr.Zero) throw new System.DllNotFoundException(path);"); + WriteLine("if (image == IntPtr.Zero) throw new global::System.DllNotFoundException(path);"); foreach (var symbol in symbols) { diff --git a/src/Generator/Types/Std/Stdlib.CLI.cs b/src/Generator/Types/Std/Stdlib.CLI.cs index eaefd5e2..e7356a9e 100644 --- a/src/Generator/Types/Std/Stdlib.CLI.cs +++ b/src/Generator/Types/Std/Stdlib.CLI.cs @@ -148,7 +148,7 @@ namespace CppSharp.Types.Std public override Type CLISignatureType(TypePrinterContext ctx) { return new CustomType( - $"System::Collections::Generic::List<{ctx.GetTemplateParameterList()}>^"); + $"::System::Collections::Generic::List<{ctx.GetTemplateParameterList()}>^"); } public override void CLIMarshalToNative(MarshalContext ctx) @@ -221,7 +221,7 @@ namespace CppSharp.Types.Std var tmpVarName = "_tmp" + ctx.ArgName; ctx.Before.WriteLine( - "auto {0} = gcnew System::Collections::Generic::List<{1}>();", + "auto {0} = gcnew ::System::Collections::Generic::List<{1}>();", tmpVarName, managedType); string retVarName = ctx.ReturnType.Type.Desugar().IsPointer() ? $"*{ctx.ReturnVarName}" : ctx.ReturnVarName; @@ -266,7 +266,7 @@ namespace CppSharp.Types.Std { var type = Type as TemplateSpecializationType; return new CustomType( - $@"System::Collections::Generic::Dictionary<{ + $@"::System::Collections::Generic::Dictionary<{ type.Arguments[0].Type}, {type.Arguments[1].Type}>^"); } diff --git a/tests/CSharp/CSharp.Gen.cs b/tests/CSharp/CSharp.Gen.cs index 19ace81e..aca08822 100644 --- a/tests/CSharp/CSharp.Gen.cs +++ b/tests/CSharp/CSharp.Gen.cs @@ -227,7 +227,7 @@ namespace CppSharp.Tests } return new CustomType( - $@"System.Collections.Generic.{ + $@"global::System.Collections.Generic.{ (ctx.MarshalKind == MarshalKind.DefaultExpression ? "List" : "IList")}<{ ctx.GetTemplateParameterList()}>"); } diff --git a/tests/Common/Common.Tests.cs b/tests/Common/Common.Tests.cs index c7d1adb4..f59039ad 100644 --- a/tests/Common/Common.Tests.cs +++ b/tests/Common/Common.Tests.cs @@ -1114,4 +1114,25 @@ This is a very long string. This is a very long string. This is a very long stri Common.PointerToPrimitiveTypedefPointerTestMethod(ref a, 100); Assert.AreEqual(100, a); } + + [Test] + public void TestConflictName() + { + using (var system = new CommonTest.System()) + { + Common.TakeConflictName(system); + Assert.That(system.Field1, Is.EqualTo(5)); + Assert.That(system.Field2, Is.EqualTo(10)); + } + } + + [Test, Ignore("This was exposed by another bug and doesn't work yet.")] + public void TestFreeFunctionReturnByValue() + { + using (var system = Common.FreeFunctionReturnByValue) + { + Assert.That(system.Field1, Is.EqualTo(5)); + Assert.That(system.Field2, Is.EqualTo(10)); + } + } } diff --git a/tests/Common/Common.cpp b/tests/Common/Common.cpp index 85b86a2d..3c14d9eb 100644 --- a/tests/Common/Common.cpp +++ b/tests/Common/Common.cpp @@ -1460,3 +1460,20 @@ bool ClassWithOverloadedOperators::operator<(const ClassWithOverloadedOperators& } int TestIndexedPropertiesInValueType::operator[](int i) { return i; } + +extern "C" +{ + void takeConflictName(struct system* self) + { + self->field1 = 5; + self->field2 = 10; + } + + struct system freeFunctionReturnByValue() + { + struct system s; + s.field1 = 5; + s.field2 = 10; + return s; + } +} // extern "C" \ No newline at end of file diff --git a/tests/Common/Common.h b/tests/Common/Common.h index ab105bcb..b8d7cac0 100644 --- a/tests/Common/Common.h +++ b/tests/Common/Common.h @@ -1549,3 +1549,16 @@ void DLL_API PointerToTypedefPointerTestMethod(LPPointerToTypedefPointerTest* lp typedef int *LPINT; void DLL_API PointerToPrimitiveTypedefPointerTestMethod(LPINT lp, int valToSet); + +// this name must match a universally accessible system function or class to reproduce the bug +struct system +{ + int32_t field1; + int32_t field2; +}; + +extern "C" +{ + DLL_API void takeConflictName(struct system* self); + DLL_API struct system freeFunctionReturnByValue(); +} // extern "C"