C#のソースやモジュールを、秀丸用のC++/CLIの.dllへとスタティックにリンクする

概要

ここでは一風変わった、C++の.dllにC#で作ったクラスを直接スタティックリンクしてしまう、といった手段をご紹介します。

C++/CLIとC#の混在プロジェクト

WindowsのC++には、C++/CLIという混成アセンブリを作成出来る言語が存在するため、
C++プロジェクトとC#プロジェクトを一緒のソリューションの中に入れ、
そのまま1つの.dllとしてコンパイルしてしまうことが可能となっています。

PICTURE

C#側とC++/CLI側の.NETのバージョンは一致させること

C#側とC++/CLI側の.NETのバージョンは一致させる必要があります。
例えば、.NET Framework 4.5.2であれば、両方ともそのバージョンを指定します。

C#側はANYCPUのModuleでのコンパイル

C#側は「ANYCPU」でコンパイルします。
そして、「Module」の指定をします。
Moduleの指定はGUI上ではできません、「.vcxproj」ファイルを直接編集します。

PICTURE

「Module」という指定をしておくことで、C#側はコンパイル時に、
「.dll」ではなく、「.netmodule」という拡張子のファイルとなります。

C++側はC#側のプロジェクトを参照しておく

C++/CLI側の参照には、C#側の「プロジェクト」そのものを参照で追加しておきましょう。

PICTURE

C++/CLI側は、「リンカー」の「追加依存のファイル」にC#側で作られる「.netmodule」を追加指定しておく

C++/CLI上でC#のクラスを利用した場合、当然その実態がC++側に存在しないことになりますので、
静的リンクの対象として、.netmoduleを指定します。

PICTURE

1つの.dllとなる

以上で、C++/CLIとC#がソース中に混ざっていても、1つの.dllにコンパイル出来ます。

備考

C#のdynamic型はC++/CLIには存在していません。
とりわけC#側のメソッドの返り値がdynamic型である場合には、C++/CLI側で対処しようとはせず、
C#側で一旦「dynamic型が無いメソッドの形へとラップ」し、
そのラップしたメソッドをC++/CLI側から利用するようにしてください。

.NET6の場合

.NET6.0でもC++/CLIへとリンク可能な netmodule生成サポートされています。
下記のような形とし、出力された.dllを.netmodule とすればC++/CLIへとリンクが可能となります。

.NET6 で netmodule 相当を出力する方法
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net6.0-windows</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <ProduceReferenceAssembly>false</ProduceReferenceAssembly>
        <OutputType>module</OutputType>
    </PropertyGroup>
</Project>