Skip to content

Commit

Permalink
feat: Support for inline attributes and aliasing (#131)
Browse files Browse the repository at this point in the history
* Initial attribute changes.

* Introduce ComAlias attribute with changes to name resolution strategy to support more complex aliasing scenario.

* Update demo assembly 4 and include in the solution

* Add unit tests to cover the enum alias using references to prove it still works across the interop boundary.

* Remove an unused member that would be incorrect in a 32-bit build and modify the extension to reflect better the intention & scope of the extension and add some documentation on the extension ExtractInt32.

* Address code style issues.

* Add support for the Names option in the build task to mirror the CLI behavior.
  • Loading branch information
bclothier authored Feb 7, 2023
1 parent f944273 commit 9a6ad4f
Show file tree
Hide file tree
Showing 38 changed files with 1,200 additions and 122 deletions.
78 changes: 61 additions & 17 deletions dscom.sln
Original file line number Diff line number Diff line change
@@ -1,72 +1,116 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
# Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dscom", "src\dscom\dscom.csproj", "{54297095-6CB9-4A75-B9C0-41ADA916C27C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dscom", "src\dscom\dscom.csproj", "{54297095-6CB9-4A75-B9C0-41ADA916C27C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dscom.client", "src\dscom.client\dscom.client.csproj", "{76139847-83FD-4982-8E8D-8C0B946D796E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dscom.client", "src\dscom.client\dscom.client.csproj", "{76139847-83FD-4982-8E8D-8C0B946D796E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dscom.demo", "dscom.demo", "{CAAB6257-7EC0-484E-9593-B60CEE8F47D1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "assembly1", "src\dscom.demo\assembly1\assembly1.csproj", "{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "assembly1", "src\dscom.demo\assembly1\assembly1.csproj", "{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "assembly2", "src\dscom.demo\assembly2\assembly2.csproj", "{B55E3947-1338-4EDF-A802-B24D91636B31}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "assembly2", "src\dscom.demo\assembly2\assembly2.csproj", "{B55E3947-1338-4EDF-A802-B24D91636B31}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "assembly3", "src\dscom.demo\assembly3\assembly3.csproj", "{1BAB2994-1423-433B-BFF0-F4698B6D4A04}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "assembly3", "src\dscom.demo\assembly3\assembly3.csproj", "{1BAB2994-1423-433B-BFF0-F4698B6D4A04}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dscom.test", "src\dscom.test\dscom.test.csproj", "{5B402A1B-18B1-4D88-804A-BC0E58EF3730}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dscom.test", "src\dscom.test\dscom.test.csproj", "{5B402A1B-18B1-4D88-804A-BC0E58EF3730}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dscom.build", "src\dscom.build\dscom.build.csproj", "{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dscom.build", "src\dscom.build\dscom.build.csproj", "{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "assembly4", "src\dscom.demo\assembly4\assembly4.csproj", "{375866D7-1313-408D-AE5A-A77E48711EDB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Debug|x86.ActiveCfg = Debug|x86
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Debug|x86.Build.0 = Debug|x86
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Release|Any CPU.Build.0 = Release|Any CPU
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Release|x86.ActiveCfg = Release|x86
{54297095-6CB9-4A75-B9C0-41ADA916C27C}.Release|x86.Build.0 = Release|x86
{76139847-83FD-4982-8E8D-8C0B946D796E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76139847-83FD-4982-8E8D-8C0B946D796E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76139847-83FD-4982-8E8D-8C0B946D796E}.Debug|x86.ActiveCfg = Debug|x86
{76139847-83FD-4982-8E8D-8C0B946D796E}.Debug|x86.Build.0 = Debug|x86
{76139847-83FD-4982-8E8D-8C0B946D796E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76139847-83FD-4982-8E8D-8C0B946D796E}.Release|Any CPU.Build.0 = Release|Any CPU
{76139847-83FD-4982-8E8D-8C0B946D796E}.Release|x86.ActiveCfg = Release|x86
{76139847-83FD-4982-8E8D-8C0B946D796E}.Release|x86.Build.0 = Release|x86
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Debug|x86.ActiveCfg = Debug|x86
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Debug|x86.Build.0 = Debug|x86
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Release|Any CPU.Build.0 = Release|Any CPU
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Release|x86.ActiveCfg = Release|x86
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B}.Release|x86.Build.0 = Release|x86
{B55E3947-1338-4EDF-A802-B24D91636B31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B55E3947-1338-4EDF-A802-B24D91636B31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B55E3947-1338-4EDF-A802-B24D91636B31}.Debug|x86.ActiveCfg = Debug|x86
{B55E3947-1338-4EDF-A802-B24D91636B31}.Debug|x86.Build.0 = Debug|x86
{B55E3947-1338-4EDF-A802-B24D91636B31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B55E3947-1338-4EDF-A802-B24D91636B31}.Release|Any CPU.Build.0 = Release|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Release|Any CPU.Build.0 = Release|Any CPU
{B55E3947-1338-4EDF-A802-B24D91636B31}.Release|x86.ActiveCfg = Release|x86
{B55E3947-1338-4EDF-A802-B24D91636B31}.Release|x86.Build.0 = Release|x86
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Debug|x86.ActiveCfg = Debug|x86
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Debug|x86.Build.0 = Debug|x86
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Release|Any CPU.Build.0 = Release|Any CPU
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Release|x86.ActiveCfg = Release|x86
{1BAB2994-1423-433B-BFF0-F4698B6D4A04}.Release|x86.Build.0 = Release|x86
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Debug|x86.ActiveCfg = Debug|x86
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Debug|x86.Build.0 = Debug|x86
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Release|Any CPU.Build.0 = Release|Any CPU
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Release|x86.ActiveCfg = Release|x86
{5B402A1B-18B1-4D88-804A-BC0E58EF3730}.Release|x86.Build.0 = Release|x86
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Debug|x86.ActiveCfg = Debug|Any CPU
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Debug|x86.Build.0 = Debug|Any CPU
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Release|Any CPU.Build.0 = Release|Any CPU
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Release|x86.ActiveCfg = Release|Any CPU
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85}.Release|x86.Build.0 = Release|Any CPU
{375866D7-1313-408D-AE5A-A77E48711EDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{375866D7-1313-408D-AE5A-A77E48711EDB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{375866D7-1313-408D-AE5A-A77E48711EDB}.Debug|x86.ActiveCfg = Debug|x86
{375866D7-1313-408D-AE5A-A77E48711EDB}.Debug|x86.Build.0 = Debug|x86
{375866D7-1313-408D-AE5A-A77E48711EDB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{375866D7-1313-408D-AE5A-A77E48711EDB}.Release|Any CPU.Build.0 = Release|Any CPU
{375866D7-1313-408D-AE5A-A77E48711EDB}.Release|x86.ActiveCfg = Release|x86
{375866D7-1313-408D-AE5A-A77E48711EDB}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{54297095-6CB9-4A75-B9C0-41ADA916C27C} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{76139847-83FD-4982-8E8D-8C0B946D796E} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{CAAB6257-7EC0-484E-9593-B60CEE8F47D1} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{419C0D96-9C17-480C-A636-1C6BEF1A3A5B} = {CAAB6257-7EC0-484E-9593-B60CEE8F47D1}
{B55E3947-1338-4EDF-A802-B24D91636B31} = {CAAB6257-7EC0-484E-9593-B60CEE8F47D1}
{5B402A1B-18B1-4D88-804A-BC0E58EF3730} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{1BAB2994-1423-433B-BFF0-F4698B6D4A04} = {CAAB6257-7EC0-484E-9593-B60CEE8F47D1}
{5B402A1B-18B1-4D88-804A-BC0E58EF3730} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{F8F68E57-CFFE-4EA5-9C1A-2CD9223B5D85} = {0A2E33B4-9DF7-4199-BC39-B0FC9C99FA97}
{375866D7-1313-408D-AE5A-A77E48711EDB} = {CAAB6257-7EC0-484E-9593-B60CEE8F47D1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3F23D9EA-A9D9-4CE5-94B5-050A9B68CA1C}
EndGlobalSection
EndGlobal
8 changes: 7 additions & 1 deletion src/dscom.build/DefaultBuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,14 @@ public bool ConvertAssemblyToTypeLib(TypeLibConverterSettings settings, TaskLogg
// Create type library converter.
var converter = new TypeLibConverter();

// Choose appropriate name resolver based on inputs with the Com Alias as the fallback.
var nameResolver = settings.Names != null && settings.Names.Any()
? NameResolver.Create(settings.Names)
: NameResolver.Create(assembly);

// Create event handler.
var sink = new LoggingTypeLibExporterSink(log);
var sink = new LoggingTypeLibExporterSink(log, nameResolver);

// create conversion.
var tlb = converter.ConvertAssemblyToTypeLib(assembly, settings, sink);
if (tlb == null)
Expand Down
12 changes: 10 additions & 2 deletions src/dscom.build/LoggingTypeLibExporterSink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,29 @@ namespace dSPACE.Runtime.InteropServices.BuildTasks;
/// Implementation of the a <see cref="ITypeLibExporterNotifySink" />
/// forwarding all messages to the MsBuild log.
/// </summary>
internal sealed class LoggingTypeLibExporterSink : ITypeLibExporterNotifySink
internal sealed class LoggingTypeLibExporterSink : ITypeLibExporterNotifySink, ITypeLibExporterNameProvider
{
/// <summary>
/// The logging sink.
/// </summary>
private readonly TaskLoggingHelper _log;

private readonly INameResolver _nameResolver;

/// <summary>
/// Creates a new instance of the <see cref="LoggingTypeLibExporterSink" />
/// using the specified <paramref name="log" /> as logging target.
/// </summary>
/// <param name="log">The log to write to.</param>
internal LoggingTypeLibExporterSink(TaskLoggingHelper log)
internal LoggingTypeLibExporterSink(TaskLoggingHelper log, INameResolver nameResolver)
{
_log = log;
_nameResolver = nameResolver;
}

public INameResolver GetNameResolver()
{
return _nameResolver;
}

/// <inheritdoc cref="ITypeLibExporterNotifySink.ReportEvent" />
Expand Down
3 changes: 2 additions & 1 deletion src/dscom.client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ private static void ConfigureTLBExportHandler(Command tlbexportCommand)

var assembly = Assembly.LoadFrom(options.Assembly);
var typeLibConverter = new TypeLibConverter();
var typeLib = typeLibConverter.ConvertAssemblyToTypeLib(assembly, options, new TypeLibExporterNotifySink(options));
var nameResolver = options.Names.Any() ? NameResolver.Create(options.Names) : NameResolver.Create(assembly);
var typeLib = typeLibConverter.ConvertAssemblyToTypeLib(assembly, options, new TypeLibExporterNotifySink(options, nameResolver));

if (typeLib is ICreateTypeLib2 createTypeLib2)
{
Expand Down
5 changes: 0 additions & 5 deletions src/dscom.client/TypeLibConverterOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ public class TypeLibConverterOptions : TypeLibConverterSettings
/// </summary>
public bool Silent { get; set; }

/// <summary>
/// Gets or sets an array if names that should be users.
/// </summary>
public string[] Names { get; set; } = Array.Empty<string>();

/// <summary>
/// Gets or sets an array of warnings that should ignored.
/// </summary>
Expand Down
28 changes: 6 additions & 22 deletions src/dscom.client/TypeLibExporterNotifySink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ namespace dSPACE.Runtime.InteropServices;
/// </summary>
public class TypeLibExporterNotifySink : ITypeLibExporterNotifySink, ITypeLibExporterNameProvider, ITypeLibCacheProvider
{
public TypeLibExporterNotifySink(TypeLibConverterOptions options)
private readonly INameResolver _nameResolver;

public TypeLibExporterNotifySink(TypeLibConverterOptions options, INameResolver nameResolver)
{
Options = options;

CollectNames();
_nameResolver = nameResolver;
}

private List<string> Names { get; } = new();

public TypeLibConverterOptions Options { get; }

public ITypeLibCache? TypeLibCache { get; set; }
Expand Down Expand Up @@ -115,24 +115,8 @@ public virtual object ResolveRef(Assembly assembly)
/// <summary>
/// Returns a list of names that can be used to specify the casing of type library elements.
/// </summary>
public virtual string[] GetNames()
{
return Names.ToArray();
}

/// <summary>
/// Read all names from all files specified in the "Names" option.
/// </summary>
private void CollectNames()
public INameResolver GetNameResolver()
{
foreach (var fileName in Options.Names)
{
if (!File.Exists(fileName))
{
throw new ArgumentException($"Given names file {fileName} does not exist.");
}

File.ReadLines(fileName).ToList().ForEach(n => Names.Add(n));
}
return _nameResolver;
}
}
14 changes: 14 additions & 0 deletions src/dscom.demo/assembly4/DemoAlias.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
using dSPACE.Runtime.InteropServices.Attributes;

namespace dSPACE.Runtime.InteropServices.DemoAssembly4;

[
ComVisible(true),
ComAlias("IFOO")
]
public interface IFoo
{
[ComAlias("DOFOO")]
void DoFoo();
}
88 changes: 88 additions & 0 deletions src/dscom.demo/assembly4/DemoHiddenAndRestricted.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Runtime.InteropServices;
using dSPACE.Runtime.InteropServices.Attributes;

namespace dSPACE.Runtime.InteropServices.DemoAssembly4;

[ComVisible(true)]
public interface IDemoInterfaceVisible
{
void DoSomething(IDemoInterfaceVisible param);
}

[
ComVisible(true),
Hidden
]
public interface IDemoInterfaceHiddenImplicit
{
void DoSomething(IDemoInterfaceHiddenImplicit param);
}

[
ComVisible(true),
Hidden(true)
]
public interface IDemoInterfaceHidden
{
void DoSomething(IDemoInterfaceHidden param);
}

[
ComVisible(true),
Hidden(true)
]
public interface IDemoInterfaceVisibleExplicit
{
void DoSomething(IDemoInterfaceVisibleExplicit param);
}

[
ComVisible(true),
Restricted
]
public interface IDemoInterfaceRestrictedImplicit
{
void DoSomething(IDemoInterfaceRestrictedImplicit param);
}

[
ComVisible(true),
Restricted(true)
]
public interface IDemoInterfaceRestricted
{
void DoSomething(IDemoInterfaceRestricted param);
}

[
ComVisible(true),
Restricted(true)
]
public interface IDemoInterfaceusableExplicit
{
void DoSomething(IDemoInterfaceusableExplicit param);
}

[
ComVisible(true),
Hidden,
Restricted
]
public interface IDemoInterfaceHiddeAndRestricted
{
void DoSomething(IDemoInterfaceHiddeAndRestricted param);
}
Loading

0 comments on commit 9a6ad4f

Please sign in to comment.