Detect and use optional external C library at runtime in Objective-C
c, ios, late-binding, objective-c, static-libraries
Solution
Use `dlsym` to get the C function pointers by function name. If it can find them, they're there. Otherwise they're not. Just use `RTLD_DEFAULT` as the first parameter.
EDIT: having cast around for an iOS example, see Mike Ash's write up of PLWeakCompatibility, particularly the section on 'Falling Through'. You'll see he checks whether `objc_loadWeakRetained` (a runtime call related to weak references) is present. Under 5+ it is and his version calls the real one directly. Under 4 it isn't so his version does something else instead.
EDIT2: sample code:
Sample 1:
#import <Foundation/Foundation.h>
#include <dlfcn.h>
int main(int argc, char *argv[])
{
@autoreleasepool
{
NSLog(@"%p", dlsym(RTLD_DEFAULT, "someFunc"));
}
}
Outputs `0x0`. Sample 2:
#import <Foundation/Foundation.h>
#include <dlfcn.h>
void someFunc()
{
}
int main(int argc, char *argv[])
{
@autoreleasepool
{
NSLog(@"%p", dlsym(RTLD_DEFAULT, "someFunc"));
}
}
Outputs an address other than 0x0.
Sample 3:
#import <Foundation/Foundation.h>
#include <dlfcn.h>
void someFunc()
{
NSLog(@"Hi!");
}
int main(int argc, char *argv[])
{
@autoreleasepool
{
void (* func)();
func = dlsym(RTLD_DEFAULT, "someFunc");
func();
}
}
Outputs `Hi!`.
Structs have no presence in a .a or elsewhere at runtime, they're just instructions to the compiler on how to format data. So you'll need to include either the actual structs or a compatible restatement of them in your code.
Problem
I am building an SDK that iPhone developers can include in their projects. It is delivered as a compiled ".a", without source code. Let's call my SDK "AAA". The customer in his project (let's call it "BBB"), in addition to use AAA, may also use a 3rd party library called "CCC" - which also comes pre-compiled, closed-source. I do not sell CCC, it's a different company. My SDK, AAA, can optionally use CCC to improve the product, using those 3rd party features. For example, let's say CCC is a security SDK to encrypt something. AAA does not require CCC, but will be more secured if the customer chooses to include CCC in their project as well. Now here is an extra tricky part - the CCC library, is pure C code, made of C Structs and C functions - nothing object-oriented about it. The issues are: - How can I compile my AAA SDK to use functions/structs from CCC, without including CCC in my project (not legally allowed to, and don't want to keep up to date with version updates). - How can I detect if the customer has CCC in his project, to use those extra features only if available?