2012-10-11 6 views
6

Mac用のMonoに移植するコードは、アンマネージC++ライブラリを呼び出します。 Macでは、アンマネージドライブラリをフレームワークに移植しました(残念ながら、ビルドプロセスでは、dylibとしてではなくFrameworkとしてコンパイルできます)。 Monoでは、ビルドされたアプリケーションの横にフレームワークファイルをコピーするプロジェクトのビルドステップを設定しました。Mac用Mono上のDllImportのネイティブライブラリの設定パス

しかし、このDLLにP/Invokeを実行すると、DllNotFound例外が発生します。私はMono Interop Wikiを読んでいて、P/Invoke on MonoはDYLD_ *環境変数が指し示す場所を見るだけで、現在のディレクトリは検索パスにはないようです。フレームワークを/ Library/Frameworksにコピーすると、私のP/Invoke呼び出しはうまくいきましたが、私のフレームワークファイルは/ Library/Frameworksではなく、Appの隣にある方が好きです。

私はP/Invoke呼び出しを行う前にDYLD_FRAMEWORK_PATH環境変数に現在の作業ディレクトリを追加しようとしましたが、System.Environment名前空間はMacのMonoで機能が制限されています。 。

私はフレームファイルをアプリケーションの隣に置いて、まだP/Invokeにアクセスできますか?

+0

'System.Environment.SetEnvironmentVariable'がMonoでは動作しないと言っていますか? –

答えて

7

環境変数を設定する方法と、MonoMacアプリケーションでネイティブフレームワークをバンドルする方法の2つの質問に分けましょう。

環境変数の設定このようなあなたは、アプリケーションのInfo.plistLSEnvironmentセクションに環境変数を設定することができ

、:

<?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
    <plist version="1.0"> 
      <dict> 
      <key>CFBundleIdentifier</key> 
      <string>com.yourcompany.TableViewTest</string> 
      <key>CFBundleName</key> 
      <string>TableViewTest2</string> 
      <key>CFBundleVersion</key> 
      <string>1</string> 
      <key>LSMinimumSystemVersion</key> 
      <string>10.6</string> 
      <key>NSMainNibFile</key> 
      <string>MainMenu</string> 
      <key>NSPrincipalClass</key> 
      <string>NSApplication</string> 
      <key>LSEnvironment</key> 
      <dict> 
        <key>Foo</key> 
        <string>Bar</string> 
      </dict> 
    </dict> 
    </plist> 

それはのように思えるが、手動で一度そのファイルを編集して追加する必要がありますするには少なくとも1つの環境変数。

ファイルはMonoDevelopによって自動的に作成されるため、LSEnvironmentセクションを追加するだけです。

その後、MonoDevelopで編集することができます。プロジェクトオプション「Mac OS Xアプリケーション」、「詳細設定」に移動します。 MonoMacアプリケーションで

バンドルネイティブフレームワーク

あなたはある、それを行うにははるかに簡単かつきれいな方法があります、MonoMacアプリケーションでネイティブフレームワークをバンドルするすべての環境変数を設定する必要はありません

小さなtest applicationsを作成しました。このフレームワークは、ネイティブObjective CアプリケーションとMonoMacの両方にフレームワークをバンドルしています。

まず、フレームワークをアプリケーションにバンドルする必要があります。現在、MonoDevelopでこれを自動的に行う方法はないので、手動でファイルをコピーするか、ビルド後のスクリプトを使用する必要があります(私の例ではcopy-framework.shを参照)。

フレームワークをYourApp.app/Contents/Frameworks/YourFramework.frameworkに入れることをお勧めします。これはXCodeがそれを処理する方法です。 Apple's Documentationも参照してください。

アプリケーションバンドル内のライブラリを参照するには、 `@executable_path '(dyld man pageを参照)を使用できます。

<dllmap>を使用してapp.configファイルを作成することをお勧めします。コードにパス名を入れる必要がないため、フレームワークのバージョンを簡単に変更できます。例えば:あなたのフレームワーク内の実際のライブラリがlibで始まるか.so/.dylibで終わる場合

<configuration> 
     <dllmap dll="TestFramework" target="@executable_path/../Frameworks/TestFramework.framework/TestFramework" /> 
    </configuration> 

することは、あなたは(上記のdllmapは、例えば、TestFramework.framework/libTestFramework.dylibファイルはありません)その名前を指定する必要があります。これはMonoのバグです。私はただ修正しました。

+0

このメソッドは、環境変数でアプリケーションへのフルパスを渡すときに機能しますが、現在の作業ディレクトリであるはずのものから相対パスを渡そうとすると失敗します。私は私のアプリケーションでいくつかのデバッグを行ったときに、cwdが/に設定されていることがわかりました。とにかく私はそれをハードコードすることなく私のアプリへの道を与えることができますか? – user408410

+0

起動ファイル 'YourApp.app/Contents/MacOS/YourApp'をシェルスクリプトで置き換えることも、MonoDevelop(https://github.com/mono/monodevelop/blob/master/main/)で作成したものを変更することもできますビルド/ MacOSX/monostub.m)。 しかし、私はちょうどこれを行うよりはるかにクリーンな方法を見つけたと思う、すぐにそれをテストし、私はそれで私の答えを更新します。 –

+0

これを行うには、実際にはクリーンで簡単な方法があります。これを動作させるためにMonoのバグを直ちに修正する必要があります。 –

関連する問題