Mengatur jalur Perpustakaan Asli untuk DllImport di Mono untuk Mac

Kode yang saya porting ke Mono untuk Mac, memanggil perpustakaan C++ yang tidak dikelola. Di Mac saya telah mem-porting perpustakaan kami yang tidak dikelola ke dalam Framework (sayangnya proses Build kami hanya mengizinkannya untuk dikompilasi sebagai Framework dan bukan sebagai dylib). Di Mono saya telah menyiapkan langkah pasca pembuatan di proyek saya untuk menyalin file Kerangka di sebelah aplikasi yang dibuat.

Tetapi ketika P/Panggil ke dll ini saya mendapatkan pengecualian DllNotFound. Saya membaca Mono Interop Wiki dan sepertinya P/Invoke di Mono hanya akan melihat lokasinya ditunjuk oleh variabel lingkungan DYLD_* dan direktori saat ini tidak ada dalam jalur pencarian. Ketika saya menyalin Framework ke/Library/Frameworks, panggilan P/Invoke saya berfungsi dengan baik, tetapi saya lebih suka file Framework saya ada di sebelah Aplikasi dan bukan di/Library/Frameworks.

Saya mencoba menambahkan direktori kerja saat ini ke variabel lingkungan DYLD_FRAMEWORK_PATH dalam kode saya sebelum saya melakukan panggilan P/Invoke, tetapi namespace System.Environment memiliki fungsi terbatas pada Mono untuk Mac dan variabel lingkungan Mendapatkan atau Mengatur tidak didukung.

Apakah saya bisa menyimpan file Framework saya di sebelah Aplikasi dan masih dapat melakukan P/Invoke?


person Shivaprasad    schedule 11.10.2012    source sumber
comment
Apakah Anda mengatakan bahwa System.Environment.SetEnvironmentVariable tidak berfungsi di Mono?   -  person David Heffernan    schedule 11.10.2012


Jawaban (1)


Mari kita bagi menjadi dua pertanyaan: cara mengatur variabel lingkungan dan cara menggabungkan kerangka kerja asli dalam aplikasi MonoMac.

Menetapkan Variabel Lingkungan

Anda dapat mengatur variabel lingkungan di bagian LSEnvironment pada Info.plist aplikasi Anda, seperti ini:

    <?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>

Sepertinya file itu harus diedit secara manual satu kali dan menambahkan setidaknya satu variabel lingkungan.

File tersebut secara otomatis dibuat oleh MonoDevelop, jadi yang perlu Anda lakukan hanyalah menambahkan bagian LSEnvironment.

Setelah itu, Anda dapat mengeditnya di MonoDevelop: buka opsi proyek, "Aplikasi Mac OS X", "Lanjutan".

Menggabungkan Kerangka Kerja Asli dalam Aplikasi MonoMac

Anda tidak perlu mengatur variabel lingkungan apa pun untuk menggabungkan kerangka kerja asli dalam Aplikasi MonoMac, ada cara yang lebih mudah dan bersih untuk melakukannya, yang juga mirip dengan cara kerja di Objective C.

Saya membuat aplikasi pengujian kecil, yang menggabungkan kerangka kerja dalam versi asli Aplikasi Objective C dan dalam aplikasi MonoMac.

Hal pertama yang perlu Anda lakukan adalah menggabungkan kerangka kerja Anda dengan aplikasi. Saat ini tidak ada cara untuk melakukan ini secara otomatis di MonoDevelop, jadi Anda perlu menyalin file secara manual atau menggunakan skrip pasca-pembuatan (lihat copy-framework.sh dalam contoh saya).

Saya akan merekomendasikan untuk memasukkan kerangka kerja ke YourApp.app/Contents/Frameworks/YourFramework.framework karena itulah cara XCode menanganinya; lihat juga Dokumentasi Apple.

Untuk mereferensikan pustaka di dalam bundel aplikasi Anda, Anda dapat menggunakan `@executable_path' (lihat halaman manual sebelumnya).

Saya akan merekomendasikan untuk membuat file app.config menggunakan <dllmap>, sehingga Anda tidak perlu memasukkan nama path apa pun ke dalam kode Anda, sehingga memudahkan untuk mengubah versi kerangka kerja. Contohnya:

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

Jika perpustakaan sebenarnya di dalam kerangka kerja Anda dimulai dengan lib atau diakhiri dengan .so / .dylib, maka Anda harus menentukan nama itu (misalnya, dllmap di atas tidak akan mengajukan TestFramework.framework/libTestFramework.dylib). Ini adalah bug di Mono, yang baru saja saya perbaiki.

person Martin Baulig    schedule 11.10.2012
comment
Metode ini berfungsi ketika saya memberikan jalur lengkap ke aplikasi saya di variabel Lingkungan tetapi gagal jika saya mencoba memberikan jalur relatif dari direktori kerja saat ini. Ketika saya melakukan debug lagi di Aplikasi saya, saya menemukan bahwa cwd disetel ke / . Apakah saya bisa memberikan jalur ke aplikasi saya tanpa harus melakukan hardcode? - person Shivaprasad; 12.10.2012
comment
Anda dapat mengganti file startup YourApp.app/Contents/MacOS/YourApp dengan skrip shell atau memodifikasi file yang dibuat oleh MonoDevelop (github.com/mono/monodevelop/blob/master/main/build/MacOSX/). Namun, saya rasa saya baru saja menemukan cara yang jauh lebih baik dan lebih bersih untuk melakukan ini, biarkan saya segera mengujinya, lalu saya akan memperbarui jawaban saya dengannya. - person Martin Baulig; 12.10.2012
comment
Oke, sebenarnya ada cara yang bersih dan mudah untuk melakukan ini - hanya perlu memperbaiki bug di Mono dengan cepat agar Anda dapat menjalankannya. - person Martin Baulig; 13.10.2012