7

背景: 私の MonoMac アプリは、sqlite3.0.8.6.dylib のカスタム ビルドを使用しています。

MyApp.app でこの dylib を使用するには、正確な手順が必要です。

ここに私が取ったいくつかのステップがあります:

  1. dylib を MyApp.app/Contents/SharedSupport にコピーしました。(関連する質問: これはサード パーティの dylib の優先される場所ですか、それとも MyApp.app/Contents/Frameworks が優先されますか?)

  2. ライブラリのインストール名が新しい場所と一致するように変更されました。

    MyApp.app/Contents/SharedSupport> otool -L libsqlite3.0.8.6.dylib 
    libsqlite3.0.8.6.dylib:
        @executable_path/../SharedSupport/libsqlite3.0.8.6.dylib (compatibility version 9.0.0, current version 9.6.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
    

問題

  1. MyApp.app/Contents/MacOS/MyApp は dylib を直接参照しないため、install_name_tool を使用して新しいライブラリの場所を指すことはできません。ライブラリは System.Data.Sqlite.dll によって参照されていると思います。
  2. ランチャー スクリプトで DYLD_FALLBACK_LIBRARY_PATH をオーバーライドすることを考えましたが、 MonoMac はスクリプトではなくバイナリ ランチャー (MyApp.app/Contents/MacOS/MyApp) を使用するようになったため、うまくいきません。

MonoMac の神々は、単純な解決策に違いないことを手伝ってくれませんか? これを機能させるために、オンとオフを問わず、数か月を費やしました。

そして、正確な手順を提供してください - この問題はすべて詳細に関するものです。

4

3 に答える 3

4

この質問に対する私の答えを見てください: MonoforMacでのDllImportのネイティブライブラリのパスの設定

バイナリランチャーは、monodevelop / main / build / MacOSX/monostub.mから提供されます。

どちらかMyApp.app/Contents/Frameworksまたは他のパスを使用できます。重要な部分は、パス名を使用しないことです。[DllImport]代わりに、他の回答で説明したように、<dllmap>使用法を追加@executable_pathします。app.config

そこにはgithubのテストアプリへのリンクもあります。

詳細な手順

  1. たとえば、内のパスを選択してMyApp.app、ネイティブdllをインストールしますContents/SharedSupport/sqlite3.0.8.6.dylib

  2. 管理対象アセンブリが配置されているディレクトリからネイティブへの相対パスを計算し、その先頭に.dll追加@executable_pathします。

    たとえば、管理対象アセンブリがに Contents/MonoBundle/MyApp.exeあり、ネイティブdllがに Contents/SharedSupport/sqlite3.0.8.6.dylibある場合、それは @executable_path/../SharedSupport/sqlite3.0.8.6.dylibです。

  3. を使用して、ライブラリのインストール名をこの相対パスに変更しinstall_name_toolます。

  4. MyApp.exe.configプロジェクトに新しいファイルを追加します。

    <configuration>
      <dllmap dll="sqlite" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" />
    </configuration>
    

    手順2で計算したパスをtargetフィールドに使用します。MonoDevelopでファイルを右クリックし、コンテキストメニューから[クイックプロパティ]を選択して、[出力ディレクトリにコピー]を有効にします。これにより、ファイルがディレクトリにコピーされるContents/MonoBundleため、のすぐ隣に配置されますMyApp.exe

  5. [DllImport ("sqlite")]コードでこれを参照するために使用します。

別の図書館がそれを参照するとき

たとえば、別のライブラリがMono.Data.Sqlite.dllそれを参照する場合、それはもう少し複雑になります。

上記と同じ手順を使用しますが、他のライブラリが[DllImport]ネイティブライブラリを参照するために使用している名前を特定し、それをに入れる必要があり<dllimport dll="..." />ます。[DllImport]ソースコードでステートメントを探すかmonodis、アセンブリで実行して次のように検索できpinvokeimplます。

// method line 679
.method assembly static hidebysig pinvokeimpl ("sqlite3" as "sqlite3_create_function" cdecl )
       default int32 sqlite3_create_function (native int db, unsigned int8[] strName, int32 nArgs, int32 nType, native int pvUser, class Mono.Data.Sqlite.SQLiteCallback func, class Mono.Data.Sqlite.SQLiteCallback fstep, class Mono.Data.Sqlite.SQLiteFinalCallback ffinal)  cil managed preservesig 
{
    // Method begins at RVA 0x0
} // end of method UnsafeNativeMethods::sqlite3_create_function

したがってMono.Data.Sqlite.dll、「sqlite3」を使用してネイティブdllを参照しているため、MyApp.exe.configファイルは次のようになります。

    <configuration>
      <dllmap dll="sqlite3" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" />
    </configuration>
于 2013-02-01T08:30:05.783 に答える
2

モノを使用している場合は注意してください。@executable_path は、実際の .EXE 実行可能ファイルではなく、mono バイナリへのパスを返します。ただし、これは Xamarin で正しく動作するはずです。

于 2013-10-25T05:04:19.460 に答える
1

を手動でロードしてみることができますsqlite dylib

[DllImport ("/usr/lib/libSystem.dylib")]
public static extern IntPtr dlopen (string path, int mode);
IntPtr p = dlopen("libsqlite3.0.8.6.dylib", 0);

もちろん、へのパスを正しく解決しますdylib

于 2013-01-28T21:14:27.467 に答える