在MonoMac应用程序中包括自定义dll和动态库

在MonoMac应用程序中包括自定义dll和动态库,mono,bundle,dylib,monomac,Mono,Bundle,Dylib,Monomac,背景:我的MonoMac应用程序使用sqlite3.0.8.6.dylib的自定义版本 我需要让MyApp.app使用此动态库的确切步骤 以下是我采取的一些步骤: 已将动态库复制到MyApp.app/Contents/SharedSupport。(相关问题:这是第三方DYLIB的首选位置还是MyApp.app/Contents/Frameworks的首选位置?) 已更改库的安装名称,使其与新位置匹配 MyApp.app/Contents/SharedSupport> otool -L li

背景:我的MonoMac应用程序使用sqlite3.0.8.6.dylib的自定义版本

我需要让MyApp.app使用此动态库的确切步骤

以下是我采取的一些步骤:

  • 已将动态库复制到MyApp.app/Contents/SharedSupport。(相关问题:这是第三方DYLIB的首选位置还是MyApp.app/Contents/Frameworks的首选位置?)

  • 已更改库的安装名称,使其与新位置匹配

    MyApp.app/Contents/SharedSupport> otool -L libsqlite3.0.8.6.dylib 
    libsqlite3.0.8.6.dylib:
        @executable_path/../SharedSupport/libsqlite3.0.8.6.dylib (compatibility version 9.0.0, current version 9.6.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
    
  • 问题

  • MyApp.app/Contents/MacOS/MyApp不直接引用动态库,因此我无法使用install_name_工具指向新库位置。我相信该库是由System.Data.Sqlite.dll引用的
  • 我曾想过在启动程序脚本中覆盖DYLD\u FALLBACK\u LIBRARY\u路径,但MonoMac现在使用的是二进制启动程序(MyApp.app/Contents/MacOS/MyApp),而不是脚本,所以我在那里运气不佳
  • 莫莫莫纳克诸神能帮助我们找到一个简单的解决方案吗?我已经花了几个月的时间,断断续续地,试图让这项工作发挥作用


    请提供确切的步骤-此问题与详细信息有关。

    您可以尝试手动加载
    sqlite
    dylib

    [DllImport ("/usr/lib/libSystem.dylib")]
    public static extern IntPtr dlopen (string path, int mode);
    IntPtr p = dlopen("libsqlite3.0.8.6.dylib", 0);
    

    当然,正确解析您的
    动态库的路径

    看看我对这个问题的回答:
    [DllImport ("/usr/lib/libSystem.dylib")]
    public static extern IntPtr dlopen (string path, int mode);
    IntPtr p = dlopen("libsqlite3.0.8.6.dylib", 0);
    

    二进制发射器来自

    您可以使用
    MyApp.app/Contents/Frameworks
    或其他路径,重要的是不要在
    [DllImport]
    中使用任何路径名,而是使用
    @executable\u path
    添加到
    app.config
    中,就像我在其他答案中解释的那样

    还有一个链接指向github上的测试应用程序

    详细说明

  • MyApp.app
    中选择一个路径以安装本机dll,例如
    Contents/SharedSupport/sqlite3.0.8.6.dylib

  • [DllImport ("/usr/lib/libSystem.dylib")]
    public static extern IntPtr dlopen (string path, int mode);
    IntPtr p = dlopen("libsqlite3.0.8.6.dylib", 0);
    
  • 计算从托管程序集所在目录到本机
    .dll
    的相对路径,并将
    @executable\u path
    前置到它

    例如,如果托管程序集位于
    Contents/MonoBundle/MyApp.exe
    和中的本机dll
    Contents/SharedSupport/sqlite3.0.8.6.dylib
    ,然后
    @executable\u path/。/SharedSupport/sqlite3.0.8.6.dylib

  • [DllImport ("/usr/lib/libSystem.dylib")]
    public static extern IntPtr dlopen (string path, int mode);
    IntPtr p = dlopen("libsqlite3.0.8.6.dylib", 0);
    
  • 使用
    install\u name\u tool
    将库的安装名称更改为此相对路径

  • 将新的
    MyApp.exe.config
    文件添加到项目中,其中包含

    <configuration>
      <dllmap dll="sqlite" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" />
    </configuration>
    
    因此
    Mono.Data.Sqlite.dll
    正在使用“sqlite3”引用本机dll,因此您的
    MyApp.exe.config
    文件如下所示:

        <configuration>
          <dllmap dll="sqlite3" target="@executable_path/../SharedSupport/sqlite3.0.8.6.dylib" />
        </configuration>
    
    
    
    如果使用mono,请小心@可执行_path将返回mono二进制文件的路径,而不是实际的.EXE可执行文件。不过,这对Xamarin应该是正确的。

    Martin,谢谢。然而,这个答案并没有提供确切的步骤。如果你真的能列出将动态库添加到.app并使其组合起作用的精确步骤,那将节省大量时间。与应用程序包相关的精确路径是什么?配置文件应该放在哪里,如何使用otool和安装工具来修改动态库等等。正如问题中提到的,我们已经花了几个月的时间试图得到一个工作顺序的步骤,所以我们一定缺少一些基本的东西。更好的可能是一个shell脚本来自动化这个过程。我已经为此启动了一个赏金,作为额外的奖励。嗯,赏金;-)。好吧,不管怎样,我今天都太累了,不能做这件事。如果你能等几天,那么我也可以考虑一些“真实的”事情。与其为此编写一些shell脚本,不如将此功能添加到MonoDevelop中。类似于“添加本机引用”,您只需选择一些.dylib和MonoDevelop就会自动将其添加到.app中。这需要使用生成的.csproj文件的命令行构建,因此需要使用脚本。不幸的是,我本周没有太多时间编写和测试脚本,但希望我刚才在回答中添加的详细说明能对您有所帮助。