Browse Source

Resolve names matching those of system functions

Fixes https://github.com/mono/CppSharp/issues/1602.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1614/head
Dimitar Dobrev 4 years ago
parent
commit
954a0cf941
  1. 2
      src/Generator/Generators/C/CCodeGenerator.cs
  2. 12
      src/Generator/Generators/C/CppMarshal.cs
  3. 9
      src/Generator/Generators/C/CppSources.cs
  4. 22
      src/Generator/Generators/CLI/CLIHeaders.cs
  5. 25
      src/Generator/Generators/CLI/CLIMarshal.cs
  6. 42
      src/Generator/Generators/CLI/CLISources.cs
  7. 14
      src/Generator/Generators/CLI/CLITypePrinter.cs
  8. 11
      src/Generator/Generators/CSharp/CSharpSources.cs
  9. 6
      src/Generator/Types/Std/Stdlib.CLI.cs
  10. 2
      tests/CSharp/CSharp.Gen.cs
  11. 21
      tests/Common/Common.Tests.cs
  12. 17
      tests/Common/Common.cpp
  13. 13
      tests/Common/Common.h

2
src/Generator/Generators/C/CCodeGenerator.cs

@ -152,7 +152,7 @@ namespace CppSharp.Generators.C
if (IsCLIGenerator) if (IsCLIGenerator)
{ {
if (@enum.Modifiers.HasFlag(Enumeration.EnumModifiers.Flags)) if (@enum.Modifiers.HasFlag(Enumeration.EnumModifiers.Flags))
WriteLine("[System::Flags]"); WriteLine("[::System::Flags]");
// A nested class cannot have an assembly access specifier as part // A nested class cannot have an assembly access specifier as part
// of its declaration. // of its declaration.

12
src/Generator/Generators/C/CppMarshal.cs

@ -272,7 +272,7 @@ namespace CppSharp.Generators.Cpp
Context.Return.Write($"({instance} == nullptr) ? nullptr : {MemoryAllocOperator} "); Context.Return.Write($"({instance} == nullptr) ? nullptr : {MemoryAllocOperator} ");
Context.Return.Write($"{QualifiedIdentifier(@class)}("); Context.Return.Write($"{QualifiedIdentifier(@class)}(");
Context.Return.Write($"(::{@class.QualifiedOriginalName}*)"); Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)");
Context.Return.Write($"{instance})"); Context.Return.Write($"{instance})");
} }
@ -409,7 +409,7 @@ namespace CppSharp.Generators.Cpp
Context.Parameter.Usage == ParameterUsage.InOut; Context.Parameter.Usage == ParameterUsage.InOut;
Context.ArgumentPrefix.Write("&"); 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 : "*"); isRef ? string.Empty : "*");
return true; return true;
} }
@ -511,7 +511,7 @@ namespace CppSharp.Generators.Cpp
PrimitiveType primitive; PrimitiveType primitive;
if (decl.Type.IsPrimitiveType(out 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); return decl.Type.Visit(this);
@ -588,7 +588,7 @@ namespace CppSharp.Generators.Cpp
&& method.Conversion == MethodConversionKind.FunctionToInstanceMethod && method.Conversion == MethodConversionKind.FunctionToInstanceMethod
&& Context.ParameterIndex == 0) && Context.ParameterIndex == 0)
{ {
Context.Return.Write($"(::{@class.QualifiedOriginalName}*)"); Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)");
Context.Return.Write(Helpers.InstanceIdentifier); Context.Return.Write(Helpers.InstanceIdentifier);
return; return;
} }
@ -596,7 +596,7 @@ namespace CppSharp.Generators.Cpp
var paramType = Context.Parameter.Type.Desugar(); var paramType = Context.Parameter.Type.Desugar();
var isPointer = paramType.SkipPointerRefs().IsPointer(); var isPointer = paramType.SkipPointerRefs().IsPointer();
var deref = isPointer ? "->" : "."; var deref = isPointer ? "->" : ".";
var instance = $"(::{@class.QualifiedOriginalName}*)" + var instance = $"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)" +
$"{Context.Parameter.Name}{deref}{Helpers.InstanceIdentifier}"; $"{Context.Parameter.Name}{deref}{Helpers.InstanceIdentifier}";
if (isPointer) if (isPointer)
@ -654,7 +654,7 @@ namespace CppSharp.Generators.Cpp
public override bool VisitEnumDecl(Enumeration @enum) public override bool VisitEnumDecl(Enumeration @enum)
{ {
Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName, Context.Return.Write("(enum ::{0}){1}", @enum.QualifiedOriginalName,
Context.Parameter.Name); Context.Parameter.Name);
return true; return true;
} }

9
src/Generator/Generators/C/CppSources.cs

@ -294,7 +294,7 @@ namespace CppSharp.Generators.Cpp
{ {
Write($"{QualifiedIdentifier(@class)}::{@class.Name}("); Write($"{QualifiedIdentifier(@class)}::{@class.Name}(");
var nativeType = $"::{@class.QualifiedOriginalName}*"; var nativeType = $"{(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*";
//WriteLine($"{nativeType} {ClassCtorInstanceParamIdentifier})"); //WriteLine($"{nativeType} {ClassCtorInstanceParamIdentifier})");
WriteLine(!withOwnNativeInstanceParam ? $"{nativeType} {ClassCtorInstanceParamIdentifier})" : WriteLine(!withOwnNativeInstanceParam ? $"{nativeType} {ClassCtorInstanceParamIdentifier})" :
$"{nativeType} {ClassCtorInstanceParamIdentifier}, bool ownNativeInstance)"); $"{nativeType} {ClassCtorInstanceParamIdentifier}, bool ownNativeInstance)");
@ -413,7 +413,8 @@ namespace CppSharp.Generators.Cpp
PushBlock(BlockKind.ConstructorBody, @class); PushBlock(BlockKind.ConstructorBody, @class);
var @params = GenerateFunctionParamsMarshal(method.Parameters, method); 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); GenerateFunctionParams(@params);
WriteLine(");"); WriteLine(");");
@ -492,7 +493,7 @@ namespace CppSharp.Generators.Cpp
var field = property?.Field; var field = property?.Field;
if (field != null) if (field != null)
{ {
Write($"((::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->"); Write($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->");
Write($"{field.OriginalName}"); Write($"{field.OriginalName}");
var isGetter = property.GetMethod == method; var isGetter = property.GetMethod == method;
@ -510,7 +511,7 @@ namespace CppSharp.Generators.Cpp
else else
{ {
if (IsNativeMethod(function)) if (IsNativeMethod(function))
Write($"((::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->"); Write($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*){Helpers.InstanceIdentifier})->");
Write($"{base.GetMethodIdentifier(function, TypePrinterContextKind.Native)}("); Write($"{base.GetMethodIdentifier(function, TypePrinterContextKind.Native)}(");
} }

22
src/Generator/Generators/CLI/CLIHeaders.cs

@ -262,10 +262,10 @@ namespace CppSharp.Generators.CLI
GenerateDeclContext(@class); GenerateDeclContext(@class);
Unindent(); Unindent();
var nativeType = string.Format("::{0}*", @class.QualifiedOriginalName); string nativeType = $"{(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*";
if (CLIGenerator.ShouldGenerateClassNativeField(@class)) if (CLIGenerator.ShouldGenerateClassNativeField(@class))
GenerateClassNativeField(@class, nativeType); GenerateClassNativeField(nativeType);
GenerateClassConstructors(@class, nativeType); GenerateClassConstructors(@class, nativeType);
@ -303,15 +303,15 @@ namespace CppSharp.Generators.CLI
WriteLine("};"); WriteLine("};");
} }
public void GenerateClassNativeField(Class @class, string nativeType) public void GenerateClassNativeField(string nativeType)
{ {
WriteLineIndent("property {0} NativePtr;", nativeType); WriteLineIndent("property {0} NativePtr;", nativeType);
Indent(); Indent();
WriteLine("property System::IntPtr {0}", Helpers.InstanceIdentifier); WriteLine("property ::System::IntPtr {0}", Helpers.InstanceIdentifier);
WriteOpenBraceAndIndent(); WriteOpenBraceAndIndent();
WriteLine("virtual System::IntPtr get();"); WriteLine("virtual ::System::IntPtr get();");
WriteLine("virtual void set(System::IntPtr instance);"); WriteLine("virtual void set(::System::IntPtr instance);");
UnindentAndWriteCloseBrace(); UnindentAndWriteCloseBrace();
NewLine(); NewLine();
@ -455,7 +455,7 @@ namespace CppSharp.Generators.CLI
GenerateDeclarationCommon(field); GenerateDeclarationCommon(field);
if (@class.IsUnion) 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); @class.Layout.Fields.Single(f => f.FieldPtr == field.OriginalPtr).Offset);
WriteLine("{0} {1};", field.Type, field.Name); WriteLine("{0} {1};", field.Type, field.Name);
@ -575,8 +575,8 @@ namespace CppSharp.Generators.CLI
public override void GenerateClassSpecifier(Class @class) public override void GenerateClassSpecifier(Class @class)
{ {
if (@class.IsUnion) if (@class.IsUnion)
WriteLine("[System::Runtime::InteropServices::StructLayout({0})]", WriteLine("[::System::Runtime::InteropServices::StructLayout({0})]",
"System::Runtime::InteropServices::LayoutKind::Explicit"); "::System::Runtime::InteropServices::LayoutKind::Explicit");
// Nested types cannot have visibility modifiers in C++/CLI. // Nested types cannot have visibility modifiers in C++/CLI.
var isTopLevel = @class.Namespace is TranslationUnit || var isTopLevel = @class.Namespace is TranslationUnit ||
@ -760,8 +760,8 @@ namespace CppSharp.Generators.CLI
: ((FunctionType)attributedType).CallingConvention; : ((FunctionType)attributedType).CallingConvention;
var interopCallConv = callingConvention.ToInteropCallConv(); var interopCallConv = callingConvention.ToInteropCallConv();
if (interopCallConv != System.Runtime.InteropServices.CallingConvention.Winapi) if (interopCallConv != System.Runtime.InteropServices.CallingConvention.Winapi)
WriteLine("[System::Runtime::InteropServices::UnmanagedFunctionPointer" + WriteLine("[::System::Runtime::InteropServices::UnmanagedFunctionPointer" +
"(System::Runtime::InteropServices::CallingConvention::{0})] ", "(::System::Runtime::InteropServices::CallingConvention::{0})] ",
interopCallConv); interopCallConv);
var visibility = !insideClass ? "public " : string.Empty; var visibility = !insideClass ? "public " : string.Empty;

25
src/Generator/Generators/CLI/CLIMarshal.cs

@ -83,9 +83,9 @@ namespace CppSharp.Generators.CLI
var delegateType = function.ToString(); var delegateType = function.ToString();
Context.Return.Write("safe_cast<{0}>(", delegateType + "^"); 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("GetDelegateForFunctionPointer(");
Context.Return.Write("System::IntPtr({0}), {1}::typeid))", Context.ReturnVarName, Context.Return.Write("::System::IntPtr({0}), {1}::typeid))", Context.ReturnVarName,
delegateType.TrimEnd('^')); delegateType.TrimEnd('^'));
return true; return true;
@ -223,9 +223,9 @@ namespace CppSharp.Generators.CLI
if (decl.Type.IsPointerTo(out function)) if (decl.Type.IsPointerTo(out function))
{ {
Context.Return.Write($"{Context.ReturnVarName} == nullptr ? nullptr : safe_cast<{typedef}>("); 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("GetDelegateForFunctionPointer(");
Context.Return.Write("IntPtr({0}), {1}::typeid))",Context.ReturnVarName, Context.Return.Write("::System::IntPtr({0}), {1}::typeid))", Context.ReturnVarName,
typedef.ToString().TrimEnd('^')); typedef.ToString().TrimEnd('^'));
return true; return true;
} }
@ -280,8 +280,7 @@ namespace CppSharp.Generators.CLI
if (@class.IsRefType && needsCopy) if (@class.IsRefType && needsCopy)
{ {
var name = Generator.GeneratedIdentifier(Context.ReturnVarName); var name = Generator.GeneratedIdentifier(Context.ReturnVarName);
Context.Before.WriteLine("auto {0} = new ::{1}({2});", name, Context.Before.WriteLine($"auto {name} = new {(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}({Context.ReturnVarName});");
@class.QualifiedOriginalName, Context.ReturnVarName);
instance = name; instance = name;
ownNativeInstance = true; ownNativeInstance = true;
@ -306,7 +305,7 @@ namespace CppSharp.Generators.CLI
instance); instance);
Context.Return.Write("::{0}(", QualifiedIdentifier(@class)); 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" : ""); 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.WriteLine($"if ({Context.Parameter.Name}->Length != {array.Size})");
supportBefore.WriteOpenBraceAndIndent(); 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(); supportBefore.UnindentAndWriteCloseBrace();
string nativeVal = string.Empty; string nativeVal = string.Empty;
@ -494,7 +493,7 @@ namespace CppSharp.Generators.CLI
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendFormat("static_cast<{0}>(", type); sb.AppendFormat("static_cast<{0}>(", type);
sb.Append("System::Runtime::InteropServices::Marshal::"); sb.Append("::System::Runtime::InteropServices::Marshal::");
sb.Append("GetFunctionPointerForDelegate("); sb.Append("GetFunctionPointerForDelegate(");
sb.AppendFormat("{0}).ToPointer())", Context.Parameter.Name); sb.AppendFormat("{0}).ToPointer())", Context.Parameter.Name);
Context.Return.Write(sb.ToString()); Context.Return.Write(sb.ToString());
@ -529,7 +528,7 @@ namespace CppSharp.Generators.CLI
ArgumentPrefix.Write("&"); 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); isRef ? string.Empty : "*", Context.Parameter.Name);
return true; return true;
} }
@ -728,12 +727,12 @@ namespace CppSharp.Generators.CLI
&& method.Conversion == MethodConversionKind.FunctionToInstanceMethod && method.Conversion == MethodConversionKind.FunctionToInstanceMethod
&& Context.ParameterIndex == 0) && Context.ParameterIndex == 0)
{ {
Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)");
Context.Return.Write("NativePtr"); Context.Return.Write("NativePtr");
return; return;
} }
Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); Context.Return.Write($"({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)");
Context.Return.Write("{0}->NativePtr", Context.Parameter.Name); Context.Return.Write("{0}->NativePtr", Context.Parameter.Name);
} }
@ -858,7 +857,7 @@ namespace CppSharp.Generators.CLI
public override bool VisitEnumDecl(Enumeration @enum) public override bool VisitEnumDecl(Enumeration @enum)
{ {
Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName, Context.Return.Write("(enum ::{0}){1}", @enum.QualifiedOriginalName,
Context.Parameter.Name); Context.Parameter.Name);
return true; return true;
} }

42
src/Generator/Generators/CLI/CLISources.cs

@ -136,18 +136,18 @@ namespace CppSharp.Generators.CLI
var qualifiedIdentifier = QualifiedIdentifier(@class); var qualifiedIdentifier = QualifiedIdentifier(@class);
PushBlock(BlockKind.Method); PushBlock(BlockKind.Method);
WriteLine("System::IntPtr {0}::{1}::get()", WriteLine("::System::IntPtr {0}::{1}::get()",
qualifiedIdentifier, Helpers.InstanceIdentifier); qualifiedIdentifier, Helpers.InstanceIdentifier);
WriteOpenBraceAndIndent(); WriteOpenBraceAndIndent();
WriteLine("return System::IntPtr(NativePtr);"); WriteLine("return ::System::IntPtr(NativePtr);");
UnindentAndWriteCloseBrace(); UnindentAndWriteCloseBrace();
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
PushBlock(BlockKind.Method); PushBlock(BlockKind.Method);
WriteLine("void {0}::{1}::set(System::IntPtr object)", WriteLine("void {0}::{1}::set(::System::IntPtr object)",
qualifiedIdentifier, Helpers.InstanceIdentifier); qualifiedIdentifier, Helpers.InstanceIdentifier);
WriteOpenBraceAndIndent(); WriteOpenBraceAndIndent();
var nativeType = $"::{@class.QualifiedOriginalName}*"; var nativeType = $"{(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*";
WriteLine("NativePtr = ({0})object.ToPointer();", nativeType); WriteLine("NativePtr = ({0})object.ToPointer();", nativeType);
UnindentAndWriteCloseBrace(); UnindentAndWriteCloseBrace();
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
@ -260,7 +260,7 @@ namespace CppSharp.Generators.CLI
WriteOpenBraceAndIndent(); WriteOpenBraceAndIndent();
WriteLine("auto __nativePtr = NativePtr;"); WriteLine("auto __nativePtr = NativePtr;");
WriteLine("NativePtr = 0;"); WriteLine("NativePtr = 0;");
WriteLine("delete (::{0}*) __nativePtr;", @class.QualifiedOriginalName); WriteLine($"delete ({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*) __nativePtr;", @class.QualifiedOriginalName);
UnindentAndWriteCloseBrace(); UnindentAndWriteCloseBrace();
} }
@ -398,7 +398,7 @@ namespace CppSharp.Generators.CLI
if (decl is Variable) if (decl is Variable)
variable = $"::{@class.QualifiedOriginalName}::{decl.OriginalName}"; variable = $"::{@class.QualifiedOriginalName}::{decl.OriginalName}";
else else
variable = $"((::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}"; variable = $"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}";
var ctx = new MarshalContext(Context, CurrentIndentation) var ctx = new MarshalContext(Context, CurrentIndentation)
{ {
@ -483,8 +483,10 @@ namespace CppSharp.Generators.CLI
string variable; string variable;
if (decl is Variable) if (decl is Variable)
variable = $"::{@class.QualifiedOriginalName}::{decl.OriginalName}"; variable = $"::{@class.QualifiedOriginalName}::{decl.OriginalName}";
else if (CLIGenerator.ShouldGenerateClassNativeField(@class))
variable = $"NativePtr->{decl.OriginalName}";
else else
variable = $"((::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}"; variable = $"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->{decl.OriginalName}";
var ctx = new MarshalContext(Context, CurrentIndentation) var ctx = new MarshalContext(Context, CurrentIndentation)
{ {
@ -543,12 +545,11 @@ namespace CppSharp.Generators.CLI
WriteLine("auto _fptr = (void (*)({0}))Marshal::GetFunctionPointerForDelegate({1}Instance).ToPointer();", WriteLine("auto _fptr = (void (*)({0}))Marshal::GetFunctionPointerForDelegate({1}Instance).ToPointer();",
args, delegateName); args, delegateName);
WriteLine("((::{0}*)NativePtr)->{1}.Connect(_fptr);", @class.QualifiedOriginalName, WriteLine($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->{@event.OriginalName}.Connect(_fptr);");
@event.OriginalName);
UnindentAndWriteCloseBrace(); 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); @event.Name, @event.Type);
UnindentAndWriteCloseBrace(); UnindentAndWriteCloseBrace();
@ -560,7 +561,7 @@ namespace CppSharp.Generators.CLI
@event.Name, @event.Type); @event.Name, @event.Type);
WriteOpenBraceAndIndent(); 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); @event.Name, @event.Type);
UnindentAndWriteCloseBrace(); UnindentAndWriteCloseBrace();
@ -630,7 +631,7 @@ namespace CppSharp.Generators.CLI
Write("{0}::{1}(", qualifiedIdentifier, @class.Name); 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); WriteLine(!withOwnNativeInstanceParam ? "{0} native)" : "{0} native, bool ownNativeInstance)", nativeType);
var hasBase = GenerateClassConstructorBase(@class, null, withOwnNativeInstanceParam); var hasBase = GenerateClassConstructorBase(@class, null, withOwnNativeInstanceParam);
@ -784,7 +785,8 @@ namespace CppSharp.Generators.CLI
if (!@class.IsAbstract) if (!@class.IsAbstract)
{ {
var @params = GenerateFunctionParamsMarshal(method.Parameters, method); var @params = GenerateFunctionParamsMarshal(method.Parameters, method);
Write("NativePtr = new ::{0}(", method.Namespace.QualifiedOriginalName); Write($@"NativePtr = new {(@class.IsUnion ? "union" : "struct")} ::{
@class.QualifiedOriginalName}(");
GenerateFunctionParams(@params); GenerateFunctionParams(@params);
WriteLine(");"); WriteLine(");");
} }
@ -867,8 +869,8 @@ namespace CppSharp.Generators.CLI
names.Add(marshal.Context.Return); names.Add(marshal.Context.Return);
} }
WriteLine("::{0} _native({1});", @class.QualifiedOriginalName, WriteLine($@"{(@class.IsUnion ? "union" : "struct")} ::{
string.Join(", ", names)); @class.QualifiedOriginalName} _native({string.Join(", ", names)});");
GenerateValueTypeConstructorCallProperties(@class); GenerateValueTypeConstructorCallProperties(@class);
} }
@ -959,7 +961,7 @@ namespace CppSharp.Generators.CLI
var isValueType = @class != null && @class.IsValueType; var isValueType = @class != null && @class.IsValueType;
if (isValueType && !IsNativeFunctionOrStaticMethod(function)) 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 param = new Parameter { Name = "(*this)" , Namespace = function.Namespace };
var ctx = new MarshalContext(Context, CurrentIndentation) var ctx = new MarshalContext(Context, CurrentIndentation)
@ -1018,7 +1020,7 @@ namespace CppSharp.Generators.CLI
if (isValueType) if (isValueType)
Write($"{valueMarshalName}."); Write($"{valueMarshalName}.");
else if (IsNativeMethod(function)) else if (IsNativeMethod(function))
Write("((::{0}*)NativePtr)->", @class.QualifiedOriginalName); Write($"(({(@class.IsUnion ? "union" : "struct")} ::{@class.QualifiedOriginalName}*)NativePtr)->");
Write("{0}(", function.OriginalName); Write("{0}(", function.OriginalName);
} }
@ -1067,7 +1069,7 @@ namespace CppSharp.Generators.CLI
{ {
WriteLine("if ({0} == nullptr) return {1};", WriteLine("if ({0} == nullptr) return {1};",
returnIdentifier, returnIdentifier,
isIntPtr ? "System::IntPtr()" : "nullptr"); isIntPtr ? "::System::IntPtr()" : "nullptr");
} }
var ctx = new MarshalContext(Context, CurrentIndentation) var ctx = new MarshalContext(Context, CurrentIndentation)
@ -1103,10 +1105,10 @@ namespace CppSharp.Generators.CLI
foreach (var param in method.Parameters.Where( foreach (var param in method.Parameters.Where(
p => p.Type.IsPrimitiveType(PrimitiveType.Char))) 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 // C++/CLI can actually handle char -> sbyte in all case, this is for compatibility with the C# generator
WriteLineIndent( 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); param.Name, (int) char.MinValue, sbyte.MaxValue);
} }
} }

14
src/Generator/Generators/CLI/CLITypePrinter.cs

@ -38,7 +38,7 @@ namespace CppSharp.Generators.CLI
if (array.SizeType == ArrayType.ArraySize.Incomplete && if (array.SizeType == ArrayType.ArraySize.Incomplete &&
array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) &&
array.QualifiedType.Qualifiers.IsConst) array.QualifiedType.Qualifiers.IsConst)
return "System::String^"; return VisitCILType(new CILType(typeof(string)), quals);
return $"cli::array<{array.Type.Visit(this)}>^"; return $"cli::array<{array.Type.Visit(this)}>^";
} }
@ -75,9 +75,9 @@ namespace CppSharp.Generators.CLI
var str = string.Empty; var str = string.Empty;
if(param.Usage == ParameterUsage.Out) if(param.Usage == ParameterUsage.Out)
str += "[System::Runtime::InteropServices::Out] "; str += "[::System::Runtime::InteropServices::Out] ";
else if (param.Usage == ParameterUsage.InOut) 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; str += type;
@ -179,8 +179,8 @@ namespace CppSharp.Generators.CLI
case PrimitiveType.Void: return "void"; case PrimitiveType.Void: return "void";
case PrimitiveType.Char16: case PrimitiveType.Char16:
case PrimitiveType.Char32: case PrimitiveType.Char32:
case PrimitiveType.WideChar: return "System::Char"; case PrimitiveType.WideChar: return "::System::Char";
case PrimitiveType.Char: return Options.MarshalCharAsManagedChar ? "System::Char" : "char"; case PrimitiveType.Char: return Options.MarshalCharAsManagedChar ? "::System::Char" : "char";
case PrimitiveType.SChar: return "signed char"; case PrimitiveType.SChar: return "signed char";
case PrimitiveType.UChar: return "unsigned char"; case PrimitiveType.UChar: return "unsigned char";
case PrimitiveType.Short: return "short"; case PrimitiveType.Short: return "short";
@ -200,7 +200,7 @@ namespace CppSharp.Generators.CLI
case PrimitiveType.IntPtr: return "IntPtr"; case PrimitiveType.IntPtr: return "IntPtr";
case PrimitiveType.UIntPtr: return "UIntPtr"; case PrimitiveType.UIntPtr: return "UIntPtr";
case PrimitiveType.Null: return "void*"; case PrimitiveType.Null: return "void*";
case PrimitiveType.String: return "System::String"; case PrimitiveType.String: return "::System::String";
} }
throw new NotSupportedException(); throw new NotSupportedException();
@ -300,7 +300,7 @@ namespace CppSharp.Generators.CLI
if (!type.Type.IsValueType) if (!type.Type.IsValueType)
result += "^"; result += "^";
return result; return $"::{result}";
} }
public override TypePrinterResult VisitUnsupportedType(UnsupportedType type, TypeQualifiers quals) public override TypePrinterResult VisitUnsupportedType(UnsupportedType type, TypeQualifiers quals)

11
src/Generator/Generators/CSharp/CSharpSources.cs

@ -375,7 +375,7 @@ namespace CppSharp.Generators.CSharp
base.GenerateDeclarationCommon(decl); base.GenerateDeclarationCommon(decl);
foreach (Attribute attribute in decl.Attributes) 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 #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) internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({TypePrinter.IntPtrType} native)
{{ {{
if (!NativeToManagedMap.TryGetValue(native, out var managed)) 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; var result = ({printedClass})managed;
if (result.{Helpers.OwnsNativeInstanceIdentifier}) if (result.{Helpers.OwnsNativeInstanceIdentifier})
result.SetupVTables(); result.SetupVTables();
@ -3423,6 +3423,11 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty
if (function.IsPure) if (function.IsPure)
return; return;
if (function.OriginalName == "system_do_it")
{
System.Diagnostics.Debugger.Break();
}
PushBlock(BlockKind.InternalsClassMethod); PushBlock(BlockKind.InternalsClassMethod);
var callConv = function.CallingConvention.ToInteropCallConv(); var callConv = function.CallingConvention.ToInteropCallConv();
@ -3555,7 +3560,7 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty
{ {
WriteLine($"var path = \"{path}\";"); WriteLine($"var path = \"{path}\";");
WriteLine("var image = CppSharp.SymbolResolver.LoadImage(ref 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) foreach (var symbol in symbols)
{ {

6
src/Generator/Types/Std/Stdlib.CLI.cs

@ -148,7 +148,7 @@ namespace CppSharp.Types.Std
public override Type CLISignatureType(TypePrinterContext ctx) public override Type CLISignatureType(TypePrinterContext ctx)
{ {
return new CustomType( return new CustomType(
$"System::Collections::Generic::List<{ctx.GetTemplateParameterList()}>^"); $"::System::Collections::Generic::List<{ctx.GetTemplateParameterList()}>^");
} }
public override void CLIMarshalToNative(MarshalContext ctx) public override void CLIMarshalToNative(MarshalContext ctx)
@ -221,7 +221,7 @@ namespace CppSharp.Types.Std
var tmpVarName = "_tmp" + ctx.ArgName; var tmpVarName = "_tmp" + ctx.ArgName;
ctx.Before.WriteLine( ctx.Before.WriteLine(
"auto {0} = gcnew System::Collections::Generic::List<{1}>();", "auto {0} = gcnew ::System::Collections::Generic::List<{1}>();",
tmpVarName, managedType); tmpVarName, managedType);
string retVarName = ctx.ReturnType.Type.Desugar().IsPointer() ? $"*{ctx.ReturnVarName}" : ctx.ReturnVarName; string retVarName = ctx.ReturnType.Type.Desugar().IsPointer() ? $"*{ctx.ReturnVarName}" : ctx.ReturnVarName;
@ -266,7 +266,7 @@ namespace CppSharp.Types.Std
{ {
var type = Type as TemplateSpecializationType; var type = Type as TemplateSpecializationType;
return new CustomType( return new CustomType(
$@"System::Collections::Generic::Dictionary<{ $@"::System::Collections::Generic::Dictionary<{
type.Arguments[0].Type}, {type.Arguments[1].Type}>^"); type.Arguments[0].Type}, {type.Arguments[1].Type}>^");
} }

2
tests/CSharp/CSharp.Gen.cs

@ -227,7 +227,7 @@ namespace CppSharp.Tests
} }
return new CustomType( return new CustomType(
$@"System.Collections.Generic.{ $@"global::System.Collections.Generic.{
(ctx.MarshalKind == MarshalKind.DefaultExpression ? "List" : "IList")}<{ (ctx.MarshalKind == MarshalKind.DefaultExpression ? "List" : "IList")}<{
ctx.GetTemplateParameterList()}>"); ctx.GetTemplateParameterList()}>");
} }

21
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); Common.PointerToPrimitiveTypedefPointerTestMethod(ref a, 100);
Assert.AreEqual(100, a); 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));
}
}
} }

17
tests/Common/Common.cpp

@ -1460,3 +1460,20 @@ bool ClassWithOverloadedOperators::operator<(const ClassWithOverloadedOperators&
} }
int TestIndexedPropertiesInValueType::operator[](int i) { return i; } 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"

13
tests/Common/Common.h

@ -1549,3 +1549,16 @@ void DLL_API PointerToTypedefPointerTestMethod(LPPointerToTypedefPointerTest* lp
typedef int *LPINT; typedef int *LPINT;
void DLL_API PointerToPrimitiveTypedefPointerTestMethod(LPINT lp, int valToSet); 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"

Loading…
Cancel
Save