Skip to content

Commit

Permalink
Extended Qt# and updated C++# so that the entire Qt can be wrapped.
Browse files Browse the repository at this point in the history
Signed-off-by: Dimitar Dobrev <[email protected]>
  • Loading branch information
ddobrev committed Jun 11, 2016
1 parent 36c5f0e commit 230685b
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 63 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
0.5.0 - 12.6.2016
Added:
- Wrapped the entire Qt.

0.0.8 - 21.12.2015
Added:
- Properly wrapped non-virtual destructors in derived types.
Expand Down
38 changes: 9 additions & 29 deletions QtSharp.CLI/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
Expand Down Expand Up @@ -168,6 +169,7 @@ static void ProcessGeneratedInlines ()

public static int Main(string[] args)
{
Stopwatch s = Stopwatch.StartNew();
var qts = FindQt();
bool found = qts.Count != 0;
bool debug = false;
Expand Down Expand Up @@ -195,36 +197,14 @@ public static int Main(string[] args)
if (!QueryQt(qt, debug))
return 1;

var modules = new List<string>
{
"QtCore",
"QtGui",
"QtWidgets",
"QtXml",
"QtDesigner",
"QtNetwork",
"QtQml",
"QtNfc",
"QtOpenGL",
"QtScriptTools",
"QtSensors",
"QtSerialPort",
"QtSvg",
"QtMultimedia",
"QtMultimediaWidgets",
"QtQuick",
"QtQuickWidgets"
};
if (debug)
{
for (var i = 0; i < modules.Count; i++)
{
modules[i] += "d";
}
}
for (int i = qt.LibFiles.Count - 1; i >= 0; i--)
{
if (!modules.Contains(QtSharp.GetModuleNameFromLibFile(qt.LibFiles[i])))
var libFile = qt.LibFiles[i];
var libFileName = Path.GetFileNameWithoutExtension(libFile);
if (Path.GetExtension(libFile) == ".exe" ||
libFileName == "QtDeclarative" || libFileName == "Qt5Declarative" ||
// QtQuickTest is a QML module but has 3 main C++ functions and is not auto-ignored
libFileName == "QtQuickTest" || libFileName == "Qt5QuickTest")
{
qt.LibFiles.RemoveAt(i);
}
Expand Down Expand Up @@ -260,7 +240,7 @@ public static int Main(string[] args)
zipArchive.CreateEntryFromFile("CppSharp.Runtime.dll", "CppSharp.Runtime.dll");
}
}

Console.WriteLine("Done in: " + s.Elapsed);
return 0;
}

Expand Down
20 changes: 16 additions & 4 deletions QtSharp/CompileInlinesPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,22 @@ private bool CompileInlines(Module module)
var pro = string.Format("{0}.pro", module.InlinesLibraryName);
var path = Path.Combine(this.Driver.Options.OutputDir, pro);
var proBuilder = new StringBuilder();
proBuilder.AppendFormat("QT += {0}\n",
string.Join(" ", from header in module.Headers
where !header.EndsWith(".h", StringComparison.Ordinal)
select header.Substring("Qt".Length).ToLowerInvariant()));
var qtModules = string.Join(" ", from header in module.Headers
where !header.EndsWith(".h", StringComparison.Ordinal)
select header.Substring("Qt".Length).ToLowerInvariant());
switch (qtModules)
{
// QtTest is only library which has a "lib" suffix to its module alias for qmake
case "test":
qtModules += "lib";
break;
// HACK: work around https://bugreports.qt.io/browse/QTBUG-54030
case "bluetooth":
qtModules += " network";
break;
}

proBuilder.AppendFormat("QT += {0}\n", qtModules);
proBuilder.Append("CONFIG += c++11\n");
proBuilder.Append("QMAKE_CXXFLAGS += -fkeep-inline-functions\n");
proBuilder.AppendFormat("TARGET = {0}\n", module.InlinesLibraryName);
Expand Down
29 changes: 25 additions & 4 deletions QtSharp/DocGeneration/Documentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ public class Documentation
{
public Documentation(string docsPath, IEnumerable<string> modules)
{
foreach (var module in modules)
// HACK: work around https://bugreports.qt.io/browse/QTBUG-54025
var documentationModules = new List<string>(modules);
const string qt3d = "Qt3D";
documentationModules.RemoveAll(d => d.StartsWith(qt3d, StringComparison.Ordinal));
documentationModules.Add(qt3d);
foreach (var module in documentationModules)
{
var entries = Get(docsPath, module);
foreach (var entry in entries)
Expand Down Expand Up @@ -238,7 +243,10 @@ private void CollectTypesDocumentation(HtmlNode documentRoot, string docFile)
}
node = node.NextSibling;
}
this.typesDocumentation.Add(docFile, nodes);
if (nodes.Count > 0)
{
this.typesDocumentation.Add(docFile, nodes);
}
}
}

Expand All @@ -254,15 +262,28 @@ public void DocumentFunction(Function function)
var functions = this.functionNodes[function.OriginalName];
var unit = function.OriginalNamespace.TranslationUnit;
var location = unit.FileName;
var node = functions.Find(
FunctionDocIndexNode node = null;
var nodes = functions.FindAll(
f => f.Location == location &&
(f.LineNumber == lineStart || f.LineNumber == lineEnd));
// incredible but we actually have a case of different functions with the same name in headers with the same name at the same line
if (nodes.Count > 0)
{
if (nodes.Count == 1)
{
node = nodes[0];
}
else
{
node = nodes.Find(n => n.FullName == function.QualifiedOriginalName);
}
}
var @params = function.Parameters.Where(p => p.Kind == ParameterKind.Regular).ToList();
int realParamsCount = @params.Count(p => !string.IsNullOrWhiteSpace(p.OriginalName) || p.DefaultArgument == null);
// functions can have different line numbers because of #defines
if (node == null || node.HRef == null)
{
var nodes = functions.FindAll(
nodes = functions.FindAll(
f => CheckLocation(f.Location, location) &&
(f.FullName == function.QualifiedOriginalName || f.Name == function.OriginalName) &&
f.Access != "private" && f.ParametersModifiers.Count == realParamsCount);
Expand Down
24 changes: 15 additions & 9 deletions QtSharp/GenerateEventEventsPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,23 @@ public override bool VisitMethodDecl(Method method)
return false;
}

if (!method.IsConstructor && (method.Name.EndsWith("Event") || method.Name == "event") &&
method.Parameters.Count == 1 && method.Parameters[0].Type.ToString().EndsWith("Event"))
if (!method.IsConstructor && (method.Name.EndsWith("Event", StringComparison.Ordinal) || method.Name == "event") &&
method.Parameters.Count == 1)
{
var name = char.ToUpperInvariant(method.Name[0]) + method.Name.Substring(1);
method.Name = "on" + name;
Method baseMethod;
if (!method.IsOverride ||
(baseMethod = ((Class) method.Namespace).GetBaseMethod(method, true, true)) == null ||
baseMethod.IsPure)
var type = method.Parameters[0].Type;
type = type.GetFinalPointee() ?? type;
Class @class;
if (type.TryGetClass(out @class) && @class.Name.EndsWith("Event", StringComparison.Ordinal))
{
this.events.Add(method);
var name = char.ToUpperInvariant(method.Name[0]) + method.Name.Substring(1);
method.Name = "on" + name;
Method baseMethod;
if (!method.IsOverride ||
(baseMethod = ((Class) method.Namespace).GetBaseMethod(method, true, true)) == null ||
baseMethod.IsPure)
{
this.events.Add(method);
}
}
}
return true;
Expand Down
37 changes: 27 additions & 10 deletions QtSharp/QFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,7 @@ public override string CSharpConstruct()

public override Type CSharpSignatureType(CSharpTypePrinterContext ctx)
{
var type = ctx.Type.Desugar();
ClassTemplateSpecialization classTemplateSpecialization;
var templateSpecializationType = type as TemplateSpecializationType;
if (templateSpecializationType != null)
classTemplateSpecialization = templateSpecializationType.GetClassTemplateSpecialization();
else
classTemplateSpecialization = (ClassTemplateSpecialization) ((TagType) type).Declaration;
return classTemplateSpecialization.Arguments[0].Type.Type;
return GetEnumType(ctx.Type);
}

public override string CSharpSignature(CSharpTypePrinterContext ctx)
Expand All @@ -33,12 +26,36 @@ public override string CSharpSignature(CSharpTypePrinterContext ctx)

public override void CSharpMarshalToNative(MarshalContext ctx)
{
ctx.Return.Write(ctx.Parameter.Name);
if (ctx.Parameter.Type.Desugar().IsAddress())
ctx.Return.Write("new global::System.IntPtr(&{0})", ctx.Parameter.Name);
else
ctx.Return.Write(ctx.Parameter.Name);
}

public override void CSharpMarshalToManaged(MarshalContext ctx)
{
ctx.Return.Write(ctx.ReturnVarName);
if (ctx.ReturnType.Type.Desugar().IsAddress())
{
var finalType = ctx.ReturnType.Type.GetFinalPointee() ?? ctx.ReturnType.Type;
var enumType = GetEnumType(finalType);
ctx.Return.Write("*({0}*) {1}", enumType, ctx.ReturnVarName);
}
else
{
ctx.Return.Write(ctx.ReturnVarName);
}
}

private static Type GetEnumType(Type mappedType)
{
var type = mappedType.Desugar();
ClassTemplateSpecialization classTemplateSpecialization;
var templateSpecializationType = type as TemplateSpecializationType;
if (templateSpecializationType != null)
classTemplateSpecialization = templateSpecializationType.GetClassTemplateSpecialization();
else
classTemplateSpecialization = (ClassTemplateSpecialization) ((TagType) type).Declaration;
return classTemplateSpecialization.Arguments[0].Type.Type;
}
}
}
21 changes: 14 additions & 7 deletions QtSharp/QtSharp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void Preprocess(Driver driver, ASTContext lib)
method.ExplicitlyIgnore();
}

// HACK: forward declarations can enable declarations to use types from other modules; ignore such declarations until properly fixed
// HACK: work around https://github.com/mono/CppSharp/issues/657
var qSignalMapper = lib.FindCompleteClass("QSignalMapper");
for (int i = qSignalMapper.Methods.Count - 1; i >= 0; i--)
{
Expand Down Expand Up @@ -98,7 +98,8 @@ public void Preprocess(Driver driver, ASTContext lib)
method.ExplicitlyIgnore();
}
}
var qCamera = lib.FindCompleteClass("QCamera");
var qCamera = lib.FindClass("QCamera").FirstOrDefault(c => !c.IsIncomplete &&
c.TranslationUnit.Module.OutputNamespace == "QtMultimedia");
var qMediaPlayer = lib.FindCompleteClass("QMediaPlayer");
foreach (var method in qCamera.Methods.Union(qMediaPlayer.Methods).Where(m => m.Parameters.Any()))
{
Expand Down Expand Up @@ -164,7 +165,9 @@ public void Postprocess(Driver driver, ASTContext lib)
{
new ClearCommentsPass().VisitLibrary(driver.ASTContext);
var modules = this.qtInfo.LibFiles.Select(l => GetModuleNameFromLibFile(l));
var s = System.Diagnostics.Stopwatch.StartNew();
new GetCommentsFromQtDocsPass(this.qtInfo.Docs, modules).VisitLibrary(driver.ASTContext);
System.Console.WriteLine("Documentation done in: {0}", s.Elapsed);
new CaseRenamePass(
RenameTargets.Function | RenameTargets.Method | RenameTargets.Property | RenameTargets.Delegate |
RenameTargets.Field | RenameTargets.Variable,
Expand All @@ -187,6 +190,15 @@ public void Postprocess(Driver driver, ASTContext lib)
{
method.ExplicitlyIgnore();
}

foreach (var module in driver.Options.Modules)
{
var prefix = Platform.IsWindows ? string.Empty : "lib";
var extension = Platform.IsWindows ? ".dll" : Platform.IsMacOS ? ".dylib" : ".so";
var inlinesLibraryFile = string.Format("{0}{1}{2}", prefix, module.InlinesLibraryName, extension);
var inlinesLibraryPath = Path.Combine(driver.Options.OutputDir, Platform.IsWindows ? "release" : string.Empty, inlinesLibraryFile);
this.wrappedModules.Add(new KeyValuePair<string, string>(module.LibraryName + ".dll", inlinesLibraryPath));
}
}

public void Setup(Driver driver)
Expand Down Expand Up @@ -257,11 +269,6 @@ public void Setup(Driver driver)
}

driver.Options.Modules.Add(module);
var prefix = Platform.IsWindows ? string.Empty : "lib";
var extension = Platform.IsWindows ? ".dll" : Platform.IsMacOS ? ".dylib" : ".so";
var inlinesLibraryFile = string.Format("{0}{1}{2}", prefix, module.InlinesLibraryName, extension);
var inlinesLibraryPath = Path.Combine(driver.Options.OutputDir, Platform.IsWindows ? "release" : string.Empty, inlinesLibraryFile);
this.wrappedModules.Add(new KeyValuePair<string, string>(module.LibraryName + ".dll", inlinesLibraryPath));
}

foreach (var systemIncludeDir in this.qtInfo.SystemIncludeDirs)
Expand Down

0 comments on commit 230685b

Please sign in to comment.