I want use function 'dlopen()' to invoke a dynamic library on iOS platform, is the function 'dlopen()' private API?
Asked
Active
Viewed 1.3k times
23
-
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 Answers
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: 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
- 9,564
- 146
- 81
- 122

NSProgrammer
- 2,387
- 1
- 24
- 27
-
-
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