2012-10-11 4 views
6

Mac 용 Mono로 포팅하는 코드에서 관리되지 않는 C++ 라이브러리를 호출합니다. Mac에서는 관리되지 않는 라이브러리를 프레임 워크로 포팅했습니다 (불행히도 빌드 프로세스는 프레임 워크로만 컴파일되어 dylib로 컴파일되지 않습니다). Mono에서 빌드 된 앱 옆에 Framework 파일을 복사하는 프로젝트 빌드 단계를 설정했습니다.Mac 용 모노 용 DllImport 네이티브 라이브러리의 경로 설정

하지만이 DLL에 P/Invoke하면 DllNotFound 예외가 발생합니다. Mono Interop Wiki을 통해 읽었을 때 Mono에서 P/Invoke가 DYLD_ * 환경 변수가 가리키는 위치 만보고 현재 경로가 검색 경로에없는 것 같습니다. Framework를/Library/Frameworks에 복사 할 때 내 P/Invoke 호출이 제대로 작동했지만 Framework 파일이/Library/Frameworks가 아닌 App 옆에 있어야합니다.

P/Invoke 호출을 수행하기 전에 DYLD_FRAMEWORK_PATH 환경 변수에 현재 작업 디렉터리를 추가하려고 시도했지만 System.Environment 네임 스페이스가 Mac 용 Mono에서 제한된 기능을 가지며 환경 변수 가져 오기 또는 설정이 지원되지 않습니다. .

어쨌든 응용 프로그램 옆에 내 프레임 워크 파일을 보관할 수 있으며 여전히 P/Invoke에 abel이 있습니까?

+0

'System.Environment.SetEnvironmentVariable'이 Mono에서 작동하지 않는다고 말하는가? –

답변

7

환경 변수를 설정하는 방법과 기본 프레임 워크를 MonoMac 응용 프로그램에 묶는 방법에 대해 설명하겠습니다.

환경 변수 설정과 같은 당신은 응용 프로그램의 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> 

그것은처럼 보인다는 수동으로 한 번 해당 파일을 편집하고 추가해야합니다 적어도 하나의 환경 변수.

파일은 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 파일을 만드는 것이 좋습니다. 따라서 코드에 경로 이름을 넣지 않아도되므로 쉽게 프레임 워크 버전을 변경할 수 있습니다. 예를 들면 : 당신이 그 이름을 (위 dllmap는 예를 들어, TestFramework.framework/libTestFramework.dylib 제출하지 않습니다) 지정해야

는 프레임 워크 내부의 실제 라이브러리는 lib 시작
<configuration> 
     <dllmap dll="TestFramework" target="@executable_path/../Frameworks/TestFramework.framework/TestFramework" /> 
    </configuration> 

경우 또는 .so/.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에서 버그를 신속하게 수정해야합니다. –