自作のダイナミックリンクライブラリをXamarin.Macで作成したアプリから読み込む方法です。
Xamarin.Macで作ったアプリでDLLを読み込めず、System.DllNotFoundExceptionがスローされる問題がなかなか解決できませんでした。
以下の方法で、正しく読み込みができるようになりました。
解決前の状況
Xamarin.Macのプロジェクトに自作のダイナミックリンクライブラリ(libSample.dylib)を追加し、ビルド時に出力ディレクトリにコピーする設定にしていました。
C#のコードで、ファイル名を「libSample.dylib」にすると正しく読み込めます。
[DllImport("libSample.dylib", CallingConvention = CallingConvention.Cdecl)]
internal static extern int MyFunc();
しかし、WindowsとMacでソースコードを共有したいため、ファイル名は「Sample.dll」にして読み込みたい。
[DllImport("Sample.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int MyFunc();
ですが、ファイル名を「Sample.dll」にすると読み込むことができませんでした。
解決策
自作のダイナミックリンクライブラリは、WindowsとMacでソースコードを共有するため、ファイル名は「Sample.dll」とします。
ダイナミックリンクライブラリを使用するC#のソースコードは次のようになっています。
internal static class NativeMethods
{
[DllImport("Sample.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int MyFunc();
}
Xamarin.Macのプロジェクトにダイナミックリンクライブラリを追加する
Xamarin.Macのプロジェクトにダイナミックリンクライブラリ(libSample.dylib)を追加します。
今回はプロジェクトの直下に配置しました。
Xamarin.Macのプロジェクトに「CustomBuildActions.targets」を追加する
Xamarin.Macのプロジェクトを右クリック→追加→Misc→空のテキストファイルを選択して、ファイル名「CustomBuildActions.targets」を新規に作成します。
「CustomBuildActions.targets」を開き、次のように記述します。
<?xml version="1.0" encoding="UTF-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CreateAppBundleDependsOn>$(CreateAppBundleDependsOn);CopyOurFiles</CreateAppBundleDependsOn>
</PropertyGroup>
<Target Name="CopyOurFiles">
<Message Text="This is us copying a file into resources!" />
<Copy SourceFiles="libSample.dylib" DestinationFiles="$(AppBundleDir)/Contents/MonoBundle/libSample.dll" />
</Target>
</Project>
これは、ビルド時に「libSample.dylib」を「$(AppBundleDir)/Contents/MonoBundle/libSample.dll”」にコピーする設定です。
次にプロジェクトファイル(csproj)を編集します。
テキストエディタでcsprojファイルを開くか、VisualStudio For Macからプロジェクトを右クリック→ツール→ファイルの編集を選択します。
Project閉じタグの直前に次の行を追加します。
<Import Project="CustomBuildActions.targets" />
プロジェクトファイル(csproj)の末尾は次のようになります。
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Mac\Xamarin.Mac.CSharp.targets" />
<Import Project="CustomBuildActions.targets" />
</Project>
これでビルド時に「CustomBuildActions.targets」の設定が実行されます。
以上で設定は完了しました。
リビルドを実行すると、DLLを正しく読み込むことができるようになりました。