火球来了 2024-03-01 10:15 采纳率: 0%
浏览 81

MAUI 安卓app调用非托管dll库文件方法

问题:我在使用MAUI编写安卓APP,遇到一个问题,就是我调用的一个dll库文件,他会再调用一个非托管的dll库文件,如果我是在写WPF或者桌面应用只需要把这个非托管的dll放到Debug文件夹里程序就能运行,但是在MAUI中,我不知道应该如果设置,他一直报错找不到这个非托管的dll文件,
请大家提供一些方法

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-03-01 10:17
    关注

    引自免费微信小程序:皆我百晓生

    在 .NET MAUI 中,由于跨平台的限制和应用打包结构的不同,直接将非托管(非委托)的 DLL 文件放在 Debug 文件夹中并不能确保它们在 Android 平台上被正确加载。你需要将这些依赖项以可移植的方式集成到你的项目中。

    针对你的情况,有以下几种可能的解决方案:

    解决方案 1:原生库集成

    如果你调用的非委托库是原生 Android 的 .so 库文件,你需要按照以下步骤操作:

    1. 将对应的 ABI 版本(例如armeabi-v7a, arm64-v8a, x86, x86_64等)的 .so 文件放入项目的 Platforms\Android\NativeLibraries 目录下。
    2. .csproj 文件中,确保 <PropertyGroup> 标签内包含正确的 Android 运行时库路径设置:
      <PropertyGroup>
        ...
        <AndroidNativeLibraries>True</AndroidNativeLibraries>
        ...
      </PropertyGroup>
      
    3. 确保 .so 文件根据不同的架构分别放置在对应的子目录下,并且在生成 APK 时会被正确打包。

    解决方案 2:使用自定义 MauiHandler 或 DependencyService

    如果非委托库提供的是 C# API(但内部调用了非托管代码),并且它是一个 P/Invoke 的封装库,那么你可以尝试通过 .NET MAUI 的 MauiHandler 或者 DependencyService 来实现跨平台调用。

    示例代码(假设封装库名为 MyUnmanaged.dll):

    // 在 MauiApp.cs 或任何初始化位置注册服务
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new MyPage();
    
            // 注册服务(仅示例,实际逻辑请根据你的库接口设计)
            DependencyService.Register<MyUnmanagedLibraryService>();
        }
    }
    
    // 创建一个服务类来处理对非托管库的调用
    public class MyUnmanagedLibraryService : IMyUnmanagedLibraryService
    {
        [DllImport("MyUnmanaged")]
        private static extern int NativeMethod();
    
        public int CallNativeMethod()
        {
            return NativeMethod();
        }
    }
    
    // 定义接口
    public interface IMyUnmanagedLibraryService
    {
        int CallNativeMethod();
    }
    

    然后,在需要使用的地方获取并调用这个服务:

    var service = DependencyService.Get<IMyUnmanagedLibraryService>();
    int result = service.CallNativeMethod();
    

    解决方案 3:嵌入资源并在运行时加载

    另一种方法是将非托管 DLL 作为资源嵌入到应用程序中,然后在 Android 平台上运行时从资源流中动态加载。然而,这种方法并不适用于所有类型的非托管库,因为并非所有平台都支持从内存加载非托管库。

    若要尝试此方法,请将非托管 DLL 添加为项目中的资源,并编写代码在运行时加载该资源并将其保存到临时文件,再加载到程序集。但由于跨平台兼容性和安全性的考量,这种方法通常不推荐用于移动应用开发。

    总结来说,对于非托管的 Android 库,请优先考虑解决方案 1;而对于封装了 P/Invoke 调用的托管库,请采用解决方案 2。在特定情况下,可以评估是否有必要使用解决方案 3,但务必注意其适用性和风险。

    评论

报告相同问题?

问题事件

  • 修改了问题 3月1日
  • 创建了问题 3月1日