在Mono for Mac上为DllImport设置本机库的路径

时间:2012-10-11 07:14:29

标签: pinvoke environment-variables monomac

我移植到Mono for Mac的代码调用了一个非托管的C ++库。在Mac上,我已将非托管库移植到框架中(不幸的是,我们的构建过程只允许将其编译为框架而不是作为dylib)。在Mono中,我在项目中设置了一个post build步骤,以复制构建应用程序旁边的Framework文件。

但是当一个P / Invoke进入这个dll时,我得到一个DllNotFound异常。我通读了Mono Interop Wiki,看起来Mono上的P / Invoke只会查看DYLD_ *环境变量指向的位置,而当前目录不在搜索路径中。当我将Framework复制到/ Library / Frameworks时,我的P / Invoke调用工作正常,但我更喜欢我的Framework文件出现在App旁边而不是/ Library / Frameworks中。

我尝试在执行任何P / Invoke调用之前将当前工作目录添加到我的代码中的DYLD_FRAMEWORK_PATH环境变量,但System.Environment命名空间在Mono for Mac上具有有限的功能,并且不支持获取或设置环境变量。

无论如何,我可以将我的框架文件保留在应用程序旁边,仍然可以使用P / Invoke吗?

1 个答案:

答案 0 :(得分:7)

让我们将其分为两个问题:如何设置环境变量以及如何在MonoMac应用程序中捆绑本机框架。

设置环境变量

您可以在应用程序LSEnvironment的{​​{1}}部分设置环境变量,如下所示:

Info.plist

似乎必须手动编辑该文件一次并添加至少一个环境变量。

该文件由MonoDevelop自动创建,因此您只需添加 <?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中编辑它们:转到项目选项,“Mac OS X应用程序”,“高级”。

在MonoMac应用程序中捆绑本机框架

您不需要设置任何环境变量来在MonoMac应用程序中捆绑本机框架,这样做更简单,更清晰,这也与目标C中的工作方式类似。

我创建了一个小test applications,它在本机Objective C应用程序和MonoMac应用程序中捆绑了一个框架。

您需要做的第一件事就是将您的框架与应用程序捆绑在一起。目前无法在MonoDevelop中自动执行此操作,因此您需要手动复制文件或使用一些构建后的脚本(请参阅我的示例中的LSEnvironment)。

我建议将框架放入copy-framework.sh,因为这是XCode处理它的方式;另见Apple's Documentation

要引用应用程序包中的库,可以使用`@executable_path'(参见dyld man page)。

我建议使用YourApp.app/Contents/Frameworks/YourFramework.framework创建app.config文件,这样就不需要在代码中添加任何路径名,从而可以更轻松地更改框架版本。例如:

<dllmap>

如果框架内的实际库以 <configuration> <dllmap dll="TestFramework" target="@executable_path/../Frameworks/TestFramework.framework/TestFramework" /> </configuration> 开头或以lib / .so结尾,则必须指定该名称(上述dllmap不会归档{{1} }, 例如)。这是Mono中的一个错误,我刚修复过。