diff --git a/src/AST/Type.cs b/src/AST/Type.cs index c7ca5f98..84b78663 100644 --- a/src/AST/Type.cs +++ b/src/AST/Type.cs @@ -282,6 +282,8 @@ namespace CppSharp.AST // Argument types. public List Parameters; + public CallingConvention CallingConvention { get; set; } + public FunctionType() { Parameters = new List(); diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index b228c0d5..6f1bb060 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -59,6 +59,8 @@ namespace CppSharp.Generators.CSharp Context.MarshalToManaged = this; } + public int VarSuffix { get; set; } + public static string QualifiedIdentifier(Declaration decl) { var names = new List { decl.Name }; @@ -207,6 +209,8 @@ namespace CppSharp.Generators.CSharp if (ctx.Kind == CSharpMarshalKind.NativeField) { string copy = Generator.GeneratedIdentifier("copy"); + if (VarSuffix > 0) + copy += VarSuffix; Context.SupportBefore.WriteLine( "var {0} = new global::System.IntPtr(&{1});", copy, instance); instance = copy; @@ -215,6 +219,8 @@ namespace CppSharp.Generators.CSharp if (@class.IsRefType) { var instanceName = Generator.GeneratedIdentifier("instance"); + if (VarSuffix > 0) + instanceName += VarSuffix; // Allocate memory for a new native object and call the ctor. Context.SupportBefore.WriteLine("var {0} = Marshal.AllocHGlobal({1});", @@ -344,9 +350,9 @@ namespace CppSharp.Generators.CSharp var pointee = pointer.Pointee; Type type = pointee.Desugar(); - if ((type.IsPrimitiveType(PrimitiveType.Char) || - type.IsPrimitiveType(PrimitiveType.WideChar)) && - pointer.QualifiedPointee.Qualifiers.IsConst) + if ((type.IsPrimitiveType(PrimitiveType.Char) || + type.IsPrimitiveType(PrimitiveType.WideChar)) && + pointer.QualifiedPointee.Qualifiers.IsConst) { Context.Return.Write("Marshal.StringToHGlobalAnsi({0})", Helpers.SafeIdentifier(Context.Parameter.Name)); diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 78e927fd..9b0e70ff 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -503,8 +503,9 @@ namespace CppSharp.Generators.CSharp GenerateStructMarshalingFields(@base.Class); } - foreach (var field in @class.Fields) + for (int i = 0; i < @class.Fields.Count; i++) { + var field = @class.Fields[i]; if (ASTUtils.CheckIgnoreField(field)) continue; var nativeField = string.Format("{0}->{1}", @@ -519,6 +520,7 @@ namespace CppSharp.Generators.CSharp }; var marshal = new CSharpMarshalNativeToManagedPrinter(ctx); + marshal.VarSuffix = i; field.Visit(marshal); if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) @@ -1438,7 +1440,7 @@ namespace CppSharp.Generators.CSharp GenerateDeclarationCommon(function); var functionName = GetFunctionIdentifier(function); - Write("public static {0} {1}(", function.ReturnType, functionName); + Write("public static {0} {1}(", function.OriginalReturnType, functionName); GenerateMethodParameters(function); WriteLine(")"); WriteStartBraceIndent(); @@ -1845,21 +1847,23 @@ namespace CppSharp.Generators.CSharp GenerateDeclarationCommon(typedef); - FunctionType function; + FunctionType functionType; TagType tag; if (typedef.Type.IsPointerToPrimitiveType(PrimitiveType.Void) - || typedef.Type.IsPointerTo(out tag)) + || typedef.Type.IsPointerTo(out tag)) { PushBlock(CSharpBlockKind.Typedef); WriteLine("public class " + SafeIdentifier(typedef.Name) + @" { }"); PopBlock(NewLineKind.BeforeNextBlock); } - else if (typedef.Type.IsPointerTo(out function)) + else if (typedef.Type.IsPointerTo(out functionType)) { PushBlock(CSharpBlockKind.Typedef); + WriteLine("[UnmanagedFunctionPointerAttribute(CallingConvention.{0})]", + Helpers.ToCSharpCallConv(functionType.CallingConvention)); WriteLine("public {0};", - string.Format(TypePrinter.VisitDelegate(function).Type, + string.Format(TypePrinter.VisitDelegate(functionType).Type, SafeIdentifier(typedef.Name))); PopBlock(NewLineKind.BeforeNextBlock); } diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index a222a94e..9c43d37b 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -140,11 +140,9 @@ namespace CppSharp.Generators.CSharp { var pointee = pointer.Pointee.Desugar(); - if (pointee.IsPrimitiveType(PrimitiveType.Char) && - pointer.QualifiedPointee.Qualifiers.IsConst) - return true; - - return false; + return (pointee.IsPrimitiveType(PrimitiveType.Char) || + pointee.IsPrimitiveType(PrimitiveType.WideChar)) && + pointer.QualifiedPointee.Qualifiers.IsConst; } public static bool IsConstCharString(QualifiedType qualType) diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index eeaa37ae..f70036fe 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -1040,6 +1040,30 @@ clang::TypeLoc ResolveTypeLoc(clang::TypeLoc TL, clang::TypeLoc::TypeLocClass Cl return TL; } +static CppSharp::AST::CallingConvention ConvertCallConv(clang::CallingConv CC) +{ + using namespace clang; + + switch(CC) + { + case CC_Default: + case CC_C: + return CppSharp::AST::CallingConvention::C; + case CC_X86StdCall: + return CppSharp::AST::CallingConvention::StdCall; + case CC_X86FastCall: + return CppSharp::AST::CallingConvention::FastCall; + case CC_X86ThisCall: + return CppSharp::AST::CallingConvention::ThisCall; + case CC_X86Pascal: + case CC_AAPCS: + case CC_AAPCS_VFP: + return CppSharp::AST::CallingConvention::Unknown; + } + + return CppSharp::AST::CallingConvention::Default; +} + CppSharp::AST::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc* TL, bool DesugarType) { @@ -1195,6 +1219,7 @@ CppSharp::AST::Type^ Parser::WalkType(clang::QualType QualType, clang::TypeLoc* auto F = gcnew CppSharp::AST::FunctionType(); F->ReturnType = GetQualifiedType(FP->getResultType(), WalkType(FP->getResultType(), &RL)); + F->CallingConvention = ConvertCallConv(FP->getCallConv()); for (unsigned i = 0; i < FP->getNumArgs(); ++i) { @@ -1474,30 +1499,6 @@ clang::CallingConv Parser::GetAbiCallConv(clang::CallingConv CC, return CC; } -static CppSharp::AST::CallingConvention ConvertCallConv(clang::CallingConv CC) -{ - using namespace clang; - - switch(CC) - { - case CC_Default: - case CC_C: - return CppSharp::AST::CallingConvention::C; - case CC_X86StdCall: - return CppSharp::AST::CallingConvention::StdCall; - case CC_X86FastCall: - return CppSharp::AST::CallingConvention::FastCall; - case CC_X86ThisCall: - return CppSharp::AST::CallingConvention::ThisCall; - case CC_X86Pascal: - case CC_AAPCS: - case CC_AAPCS_VFP: - return CppSharp::AST::CallingConvention::Unknown; - } - - return CppSharp::AST::CallingConvention::Default; -} - static const clang::CodeGen::CGFunctionInfo& GetCodeGenFuntionInfo( clang::CodeGen::CodeGenTypes* CodeGenTypes, clang::FunctionDecl* FD) { diff --git a/tests/Basic/Basic.cpp b/tests/Basic/Basic.cpp index a45acbed..1744ff77 100644 --- a/tests/Basic/Basic.cpp +++ b/tests/Basic/Basic.cpp @@ -71,15 +71,25 @@ int Hello::RetEnum(Enum e) return (int)e; } -int unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int)) +int unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int)) { return ret.A; } +const wchar_t* wcharFunction(const wchar_t* constWideChar) +{ + return constWideChar; +} + Bar operator+(const Bar& b1, const Bar& b2) { Bar b; b.A = b1.A + b2.A; b.B = b1.B + b2.B; return b; -} +} + +Bar indirectReturn() +{ + return Bar(); +} diff --git a/tests/Basic/Basic.h b/tests/Basic/Basic.h index 4dc74cf5..7c4ae134 100644 --- a/tests/Basic/Basic.h +++ b/tests/Basic/Basic.h @@ -73,4 +73,6 @@ public: DLL_API Bar operator+(const Bar &, const Bar &); -int DLL_API unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int)); +int DLL_API unsafeFunction(const Bar& ret, char* testForString, void (*foo)(int)); + +DLL_API Bar indirectReturn();