Is the function 'dlopen()' private API?
Asked Answered
A

1

23

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

Amblyoscope answered 30/6, 2011 at 6:19 Comment(1)
no. Its mentioned in docs. developer.apple.com/library/prerelease/ios/documentation/…P
K
25

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.

[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]);
    }
}
Kavanagh answered 17/6, 2014 at 14:28 Comment(6)
You haven't run into any problems with App Store rejections?History
@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.Kavanagh
Can you help me with example? How to load dynamic framework using dlopen?Mccandless
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. developer.apple.com/library/mac/documentation/Darwin/Reference/…Kavanagh
@Kavanagh 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?Dekeles
@Dekeles 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.Kavanagh

© 2022 - 2024 — McMap. All rights reserved.