Xamarin-Android-动态加载.NET程序集中嵌入的本机C库

我正在尝试动态加载在Xamarin-Android应用中使用的,在构建时嵌入在.NET库中的自定义本机C库。

我要执行的过程是:

  • 我构建.NET库并将C库嵌入其中。 -有效
  • 我为使用我的.NET库的Android开发了Xamarin应用。 -有效
  • 在运行时,.NET将C库提取到我的应用的files文件夹-Works
  • 提取C库后,我将使用dlopen动态加载它。 -失败

如上所述,最后一步失败,并显示以下消息:

library /data/user/0/com.companyname.namespace/files/mylibrary.so" needed or dlopened by "(unknown)" is not
accessible for the namespace: [name="(anonymous)",ld_library_paths="",default_library_paths="/data/app/com.companyname.namespace-O7aSwdg3bwneAoiHpkw1zg==/lib/arm64:/data/app/com.companyname.namespace-O7aSwdg3bwneAoiHpkw1zg==/base.apk!/lib/arm64-v8a",permitted_paths=""]

现在,我知道从API 24开始,Android的政策已更改,以防止开发人员加载不属于NDK的本机库(请参阅此版本changelog)。

但是,根据this blogthis other blog看来,他们似乎更多是在劝说人们不要这样做,而不是完全阻止这样做,因此我正在尝试实现声音。

我尝试了第一个博客的建议,它与案例的区别在于我正在使用C#调用android_create_namespaceandroid_dlopen_ext以及创建结构。当我获得地址时,对android_create_namespace的调用似乎可以工作,但是无论我尝试如何,对android_dlopen_ext的调用都会返回NULL。

请参见下面的代码,AndroidDlopen是发生问题的核心功能:

internal static class AndroidNative
    {
        private const string LibName = "libandroid";

        private const int ANDROID_DLEXT_USE_NAMESPACE = 0x200;
        private const int RTLD_LOCAL = 0x0;
        private const int RTLD_NOW = 0x00002;
        private const int RTLD_LAZY = 0x00001;

        [DllImport(LibName)]
        public static extern int __android_log_print(int prio,string tag,string fmt);

        [StructLayout(LayoutKind.Sequential)]
        public struct AndroidDlextinfo
        {
            public ulong flags;
            public int libraryFd;
            public long libraryFdOffset;
            public IntPtr libraryNamespace;
            public int RelroFd;
            public IntPtr ReservedAddr;
            public uint ReservedSize;
        }

        public enum AndroidNamespaceType : ulong
        {
            Regular = 0,Isolated = 1,Shared = 2,GreyListEnabled = 0x08000000,SharedIsolated = Shared | Isolated
        };

        [DllImport(LibName,EntryPoint = "android_create_namespace",CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr AndroidCreateNamespace(string name,string ldlibraryPath,string defaultlibraryPath,AndroidNamespaceType type,string permittedWhenIsolatedPath,IntPtr parent);

        [DllImport(LibName,EntryPoint = "android_dlopen_ext",CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr androidDlopenExt(string filename,int flags,AndroidDlextinfo info);

        public static IntPtr AndroidDlopen(string name)
        {
            string chirpAssemblyFolder = chirpDataHandler.chirpUserFolder;

            IntPtr chirpNamespace = AndroidCreateNamespace("trustme","/system/lib64/",AndroidNamespaceType.SharedIsolated,"/system/:/data/:/vendor/",IntPtr.Zero);

            AndroidDlextinfo androidDlextinfo = new AndroidDlextinfo
            {
                flags = ANDROID_DLEXT_USE_NAMESPACE,libraryNamespace = chirpNamespace,};

            IntPtr handle = androidDlopenExt(Path.Combine(chirpAssemblyFolder,name),RTLD_NOW,androidDlextinfo);
            return handle;
        }
    }

我知道,如果我将C库包含在Android应用程序的构建中,这是有可能的,但就我而言,此解决方案不是一个选择。

因此,我想知道最后我在做什么是否可行,如果可以,获得一些帮助以找出我在做什么的地方出了问题。谢谢!

参考文献:

ch446909360 回答:Xamarin-Android-动态加载.NET程序集中嵌入的本机C库

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3165901.html

大家都在问