diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index d8152864..34e74d24 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -2003,7 +2003,7 @@ internal static bool {Helpers.TryGetNativeToManagedMappingIdentifier}(IntPtr nat if (hasReturn && isPrimitive && !isSetter) { - WriteLine($"return { Helpers.ReturnIdentifier};"); + WriteLine($"return {Helpers.ReturnIdentifier};"); return; } @@ -2322,8 +2322,7 @@ internal static bool {Helpers.TryGetNativeToManagedMappingIdentifier}(IntPtr nat @class.HasNonTrivialDestructor && !@class.IsAbstract) { NativeLibrary library; - if (!Options.CheckSymbols || - Context.Symbols.FindLibraryBySymbol(dtor.Mangled, out library)) + if (!Options.CheckSymbols || Context.Symbols.FindLibraryBySymbol(dtor.Mangled, out library)) { // Normally, calling the native dtor should be controlled by whether or not we // we own the underlying instance. (i.e. Helpers.OwnsNativeInstanceIdentifier). @@ -3559,12 +3558,24 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty return; PushBlock(BlockKind.InternalsClassMethod); - var callConv = function.CallingConvention.ToInteropCallConv(); - WriteLine("[SuppressUnmanagedCodeSecurity, DllImport(\"{0}\", EntryPoint = \"{1}\", CallingConvention = __CallingConvention.{2})]", - GetLibraryOf(function), - function.Mangled, - callConv); + string callConv = ""; + string libImportType = "LibraryImport"; + string functionKeyword = "partial"; + + if (Options.LibraryImportType == LibraryImportType.DllImport) + { + callConv = $", CallingConvention = CallingConvention.{function.CallingConvention.ToInteropCallConv()}"; + libImportType = "DllImport"; + functionKeyword = "extern"; + } + + WriteLine("[SuppressUnmanagedCodeSecurity, {0}(\"{1}\", EntryPoint = \"{2}\"{3})]", + libImportType, + GetLibraryOf(function), + function.Mangled, + callConv + ); if (function.ReturnType.Type.IsPrimitiveType(PrimitiveType.Bool)) WriteLine("[return: MarshalAs(UnmanagedType.I1)]"); @@ -3572,7 +3583,9 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty TypePrinterResult retType; var @params = GatherInternalParams(function, out retType); - WriteLine("internal static extern {0} {1}({2});", retType, + WriteLine("internal static {0} {1} {2}({3});", + functionKeyword, + retType, GetFunctionNativeIdentifier(function), string.Join(", ", @params)); PopBlock(NewLineKind.BeforeNextBlock); diff --git a/src/Generator/Options.cs b/src/Generator/Options.cs index f42236cd..71aef044 100644 --- a/src/Generator/Options.cs +++ b/src/Generator/Options.cs @@ -2,11 +2,13 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; +using System.Runtime.Versioning; using System.Text; using CppSharp.AST; using CppSharp.Generators; using CppSharp.Passes; - +using Module = CppSharp.AST.Module; namespace CppSharp { public enum GenerationOutputMode @@ -15,10 +17,28 @@ namespace CppSharp FilePerUnit } + + /// + /// Specifies the type of interop attribute to be used in the generated bindings. + /// + public enum LibraryImportType + { + /// + /// Represents the attribute, + /// + DllImport, + + /// + /// Represents the attribute, + /// + LibraryImport + } + public class DriverOptions { public DriverOptions() { + OutputDir = Directory.GetCurrentDirectory(); SystemModule = new Module("Std") { OutputNamespace = string.Empty }; @@ -84,6 +104,14 @@ namespace CppSharp public string OutputDir; + /// + /// C# only: Specifies the type of interop attribute to be used in the generated bindings. + /// Default value is dependent on target framework version + /// + + public LibraryImportType LibraryImportType { get; set; } = GetLibraryImportType(); + + public bool OutputInteropIncludes; public bool GenerateFunctionTemplates; /// @@ -111,7 +139,7 @@ namespace CppSharp /// public bool GenerateObjectOverrides; - //List of include directories that are used but not generated + // List of include directories that are used but not generated public List NoGenIncludeDirs; /// @@ -261,6 +289,22 @@ namespace CppSharp public TranslationUnitPassCallBack TranslationUnitPassPostCallBack { get; set; } + internal static LibraryImportType GetLibraryImportType() + { + + var targetFrameworkInfo = Assembly.GetCallingAssembly() + .GetCustomAttribute() + .FrameworkName.Split(","); + + var targetFrameworkVer = float.Parse(targetFrameworkInfo[1].Split("Version=")[1].Trim('v')); + if (targetFrameworkVer >= 7.0) + { + return LibraryImportType.LibraryImport; + } + + return LibraryImportType.DllImport; + } + #endregion } @@ -269,6 +313,7 @@ namespace CppSharp public InvalidOptionException(string message) : base(message) { + } } }