为Mono for Mac设置DllImport的Native Library的路径 [英] Setting path of the Native Library for DllImport on Mono for Mac

查看:210
本文介绍了为Mono for Mac设置DllImport的Native Library的路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



但是当一个P / Invoke进入这个DLL时,我得到一个DllNotFound异常。我阅读了 Mono Interop Wiki ,似乎P / Invoke on Mono只会查看位置指向DYLD_ *环境变量,当前目录不在搜索路径中。当我将框架复制到/ Library / Frameworks时,我的P / Invoke调用工作正常,但我希望我的框架文件存在于应用程序旁边,而不是/ Library / Frameworks中。



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



有没有办法我可以保持我的框架文件旁边的应用程序,仍然是abel的P / Invoke? / p>

解决方案

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

设置环境变量



您可以在中设置环境变量,您的应用程序的 Info.plist 的LSEnvironment 部分,如下所示:

 <?xml version =1.0encoding =UTF-8?> 
<!DOCTYPE plist PUBLIC - // Apple // DTD PLIST 1.0 // ENhttp://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>

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

该文件由MonoDevelop自动创建,因此您只需添加 LSEnvironment 部分。



之后,您可以在MonoDevelop中编辑它们:转到项目选项Mac OS X应用程序,高级。



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



您不需要设置任何环境变量来捆绑MonoMac中的本机框架应用程序,有一个更容易和更干净的方法来做,这也类似于Objective C中的工作原理。



我创建了一个小的测试应用程序,它将本机Objective C应用程序和MonoMac应用程序中的框架捆绑在一起。 / p>

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



我建议将框架放入 YourApp.app/Contents/Frameworks/YourFramework.framework as这就是XCode如何处理它;另请参阅 Apple的文档



要引用应用程序包中的库,可以使用`@executable_path'(请参阅 dyld手册页)。



I建议使用< dllmap> 创建一个app.config文件,因此您不需要将任何路径名放入代码,从而更容易更改框架版本。例如:

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

如果您的框架中的实际库以 lib 或以 .so / .dylib 结束,那么您必须指定该名称(上述dllmap不会文件 TestFramework.framework / libTestFramework.dylib ,例如)。这是Mono中的一个错误,我刚刚修复。


The code I am porting to Mono for Mac, calls into a unmanaged C++ library. On the Mac I have ported our unmanaged library into a Framework(unfortunately our Build process only allows it to be compiled as a Framework and not as a dylib). In Mono I have set up a post build step in my project to copy the Framework file next to the built app.

But when a P/Invoke into this dll I get a DllNotFound exception. I read through the Mono Interop Wiki and it seems P/Invoke on Mono will only look at the locations pointed to by the DYLD_* environment variables and the current directory is not in the search path. When I copied the Framework to /Library/Frameworks, my P/Invoke calls worked fine, but I would prefer my Framework files to be present next to the App and not in /Library/Frameworks.

I tried adding the current working directory to the DYLD_FRAMEWORK_PATH environment variable in my code before I do any P/Invoke calls, but the System.Environment namespace has limited functionality on Mono for Mac and Getting or Setting environment variables is not supported.

Is there anyway I can keep my Framework files next to the App and still be abel to P/Invoke?

解决方案

Let's split this into two questions: how to set environment variables and how to bundle native frameworks in a MonoMac application.

Setting Environment Variables

You can set environment variables in the LSEnvironment section of your application's Info.plist, like this:

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

It seems like to have to manually edit that file once and add at least one environment variable.

The file is automatically created by MonoDevelop, so all you have to do is to add the LSEnvironment section.

After that, you can edit them in MonoDevelop: go to project options, "Mac OS X Application", "Advanced".

Bundling Native Frameworks in a MonoMac Application

You don't need to set any environment variables to bundle a native framework in a MonoMac Application, there's a much easier and cleaner way to do it, which is also similar to how things work in Objective C.

I created a small test applications, which bundles a framework both in a native Objective C application and in a MonoMac one.

The first thing you need to do is bundle your framework with the app. There currently is no way of doing this automatically in MonoDevelop, so you need to manually copy the files or use some post-build script (see copy-framework.sh in my example).

I would recommend to put the framework into YourApp.app/Contents/Frameworks/YourFramework.framework as that's how XCode handles it; see also Apple's Documentation.

To reference a library inside your application bundle, you can use `@executable_path' (see the dyld man page).

I would recommend to create an app.config file using <dllmap>, so you don't need to put any pathnames into your code, thus making it easier to change framework versions. For instance:

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

If the actual library inside your framework starts with lib or ends with .so / .dylib, then you must specify that name (the above dllmap won't file TestFramework.framework/libTestFramework.dylib, for instance). This is a bug in Mono, which I just fixed.

这篇关于为Mono for Mac设置DllImport的Native Library的路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆