21

I want use function 'dlopen()' to invoke a dynamic library on iOS platform, is the function 'dlopen()' private API?

Honey
  • 24,125
  • 14
  • 123
  • 212
Donald
  • 253
  • 1
  • 2
  • 10
  • Hey @Donald can you accept my answer for future observers of this question? – NSProgrammer Jan 05 '15 at 17:10
  • no. Its mentioned in docs. https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW3 – Mike Glukhov Mar 06 '15 at 07:59

1 Answers1

22

I've had success using dlopen on iOS for years. In my use case, I use dlopen to load public system frameworks on demand instead of having them loaded on app launch. Works great!

[EDIT] - as of iOS 8, extensions and shared frameworks are prohibited from using dlopen, however the application itself can still use dlopen (and is now documented as being supported for not only Apple frameworks, but custom frameworks too). See the Deploying a Containing App to Older Versions of iOS section in this Apple doc: https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf

[EDIT] - contrived example

#import <dlfcn.h>

void printApplicationState()
{
    Class UIApplicationClass = NSClassFromString(@"UIApplication");
    if (Nil == UIApplicationClass) {
        void *handle = dlopen("System/Library/Frameworks/UIKit.framework/UIKit", RTLD_NOW);
        if (handle) {
            UIApplicationClass = NSClassFromString(@"UIApplication");
            assert(UIApplicationClass != Nil);
            NSInteger applicationState = [UIApplicationClass applicationState];
            printf("app state: %ti\n", applicationState);
            if (0 != dlclose(handle)) {
                printf("dlclose failed! %s\n", dlerror());
            }
        } else {
            printf("dlopen failed! %s\n", dlerror());
        }
    } else {
        printf("app state: %ti\n", [UIApplicationClass applicationState]);
    }
}
Pang
  • 8,605
  • 144
  • 77
  • 113
NSProgrammer
  • 2,328
  • 1
  • 21
  • 27
  • You haven't run into any problems with App Store rejections? – David Liu Aug 01 '14 at 18:06
  • 1
    @DavidLiu - nope, no problems. You can't link with any unsigned binaries, but there is no issue using dlopen with OS provided public frameworks or dynamic libraries. This may have changed, but I've worked at 2 companies and done this: 1 with roughtly 1.5 million MAU and 1 with 150 million MAU. – NSProgrammer Aug 01 '14 at 21:28
  • Can you help me with example? How to load dynamic framework using dlopen? – Baljeet Singh Dec 27 '14 at 07:02
  • `void* handle = dlopen("/System/Library/Frameworks/UIKit.framework/UIKit", RTLD_NOW);` and then you can unload (decrement the load count by 1) by calling `dlclose(handle);`. Be sure to read the docs for more info. https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dlopen.3.html – NSProgrammer Dec 27 '14 at 16:23
  • @NSProgrammer how are you able to use @imports/#imports? It seems a good way for you to skip loading hundreds of shared dylibs, but I am not sure how you would be able to compile and usage of UIKit for example... Any ideas? – iOSAddicted Nov 14 '17 at 16:30
  • @iOSAddicted the imports are not the issue, it's the linker that will be the issue. Calling a symbol of a dylib will force the link to be resolved at link time which won't be the case with dyld loading. The solution is to use indirection -- NSClassFromString for example and NSSelectorFromString. For enums, you're fine, but for extern constants you'll need to duplicate the value to a var/const local to your binary. It's a pain, but doable. – NSProgrammer Oct 26 '18 at 03:08