2012-10-11 28 views
6

Kod, który przekazuję do Mono dla Mac, wywołuje niezarządzaną bibliotekę C++. Na komputerze Mac przeniesiłem naszą niezarządzaną bibliotekę do frameworka (niestety nasz proces kompilacji pozwala tylko na kompilację jako framework, a nie na dylib). W Mono utworzyłem krok do kompilacji postu w moim projekcie, aby skopiować plik Framework obok zbudowanej aplikacji.Ścieżka ustawień biblioteki rodzimej dla DllImport na Mono dla Maca

Ale kiedy P/Invoke do tej biblioteki dll dostaję wyjątek DllNotFound. Przeczytałem Mono Interop Wiki i wygląda na to, że P/Invoke on Mono będzie tylko patrzył na lokalizacje wskazane przez zmienne środowiskowe DYLD_ *, a bieżący katalog nie znajduje się w ścieżce wyszukiwania. Kiedy kopiowałem Framework do/Library/Frameworks, moje wywołania P/Invoke działały dobrze, ale wolałbym, aby moje pliki Framework były obecne obok aplikacji, a nie w/Library/Frameworks.

Próbowałem dodać bieżący katalog roboczy do zmiennej środowiskowej DYLD_FRAMEWORK_PATH w moim kodzie, zanim wykonam jakiekolwiek wywołania P/Invoke, ale przestrzeń nazw System.Environment ma ograniczoną funkcjonalność w Mono dla Maca, a zmienne środowiskowe Getting lub Setting nie są obsługiwane .

Czy mimo to mogę przechowywać moje pliki Framework obok aplikacji i nadal korzystać z P/Invoke?

+0

Czy mówisz, że 'System.Environment.SetEnvironmentVariable' nie działa w Mono? –

Odpowiedz

7

Podzielmy to na dwa pytania: jak ustawić zmienne środowiskowe i jak łączyć natywne frameworki w aplikacji MonoMac.

Ustawianie zmiennych środowiskowych

Można ustawić zmienne środowiskowe w sekcji LSEnvironment swojej aplikacji na Info.plist, podobnie jak to:

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

Wydaje się musiał ręcznie edytować ten plik raz i dodać co najmniej jedną zmienną środowiskową.

Plik jest automatycznie tworzony przez MonoDevelop, więc wszystko, co musisz zrobić, to dodać sekcję LSEnvironment.

Następnie można edytować je w MonoDevelop: przejdź do opcji projektu, "Aplikacja Mac OS X", "Zaawansowane".

Bundling Native szkieletowe w aplikacji Monoman

Nie trzeba ustawiać żadnych zmiennych środowiskowych do bundle native ramy w Monoman zgłoszeniu, istnieje o wiele łatwiejsze i bardziej przejrzysty sposób to zrobić, co jest Podobnie jest z działaniem w Objective C.

Stworzyłem mały test applications, który łączy strukturę zarówno w natywnej aplikacji C z celami, jak i w MonoMac.

Pierwszą rzeczą, którą musisz zrobić, to powiązać swój framework z aplikacją. W tej chwili nie ma możliwości zrobienia tego automatycznie w MonoDevelop, więc musisz ręcznie skopiować pliki lub użyć skryptu po budowaniu (w moim przykładzie zobacz copy-framework.sh).

Polecam umieścić ramkę w YourApp.app/Contents/Frameworks/YourFramework.framework, ponieważ obsługuje ją XCode; patrz także Apple's Documentation.

Aby odwołać się do biblioteki wewnątrz pakietu aplikacji, można użyć `@executable_path '(zobacz dyld man page).

Zalecam utworzenie pliku app.config przy użyciu <dllmap>, więc nie trzeba umieszczać żadnych ścieżek w kodzie, co ułatwia zmianę wersji szkieletu. Na przykład:

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

Jeżeli rzeczywista biblioteka wewnątrz ramy zaczyna się lub kończy lib.so/.dylib, następnie należy podać tę nazwę (Powyższe dllmap nie złoży TestFramework.framework/libTestFramework.dylib, na przykład). To jest błąd w Mono, który właśnie naprawiłem.

+0

Ta metoda działa, gdy podaję pełną ścieżkę do mojej aplikacji w zmiennej Środowisko, ale kończy się niepowodzeniem, jeśli próbuję podać względne ścieżki z bieżącego katalogu roboczego. Kiedy robiłem więcej debugowania w mojej aplikacji, stwierdziłem, że cwd jest ustawione na /. Czy mimo to mogę podać ścieżkę do mojej aplikacji bez konieczności jej kodowania? – user408410

+0

Można zastąpić plik startowy 'YourApp.app/Contents/MacOS/YourApp' skryptem powłoki lub zmodyfikować ten, który został utworzony przez MonoDevelop (https://github.com/mono/monodevelop/blob/master/main/ build/MacOSX/monostub.m). Jednak myślę, że właśnie znalazłem o wiele lepszy i czystszy sposób robienia tego, lemme szybko go przetestuj, a następnie zaktualizuję moją odpowiedź. –

+0

OK, w rzeczywistości jest to czysty i łatwy sposób robienia tego - wystarczy szybko naprawić błąd w Mono, aby to zadziałało. –