One Quickie

Weak Linking in a Plugin (Tools->General)
I've got some useful utilities in a .c file that I use for some debugging things. And I'm also writing a plugin that will go into an app I don't control. I also have a test harness that I can load the plugin and do effective debugging. This debugging file has some static variables that it uses to control things, like whether to emit log messages, or do other diagnoses.

The problem is, if I include the usefulStuff.c in my plugin and my test harness, there are two copies of the static variables, and the test harness can't control the plugin. If I don't include usefulStuff.c in the plugin I get link errors. If I don't declare as weak linked the functions I use, I'll get errors when the final program loads the plugin. Sucks to be me.

Here's one way of doing it (which is kinda hacky, but after spending a day inside of the ld man page, and other pain, the fact it works is good enough for me for right now).

In the source file for the plugin that uses stuff from usefulStuff:

Declare the function to be weak:

extern void BWDebugLog (int blah, char *blah) __attribute__((weak_import));
(you can also do this in your header files. In this case, I didn't want to touch the header)

Before you use the function, make sure it's not NULL. Note there's no trailing () after the function name.

if (BWDebugLog != NULL) {
    BWDebugLog (23, "stuff");
In the Xcode project for the plugin

Add the flags -flat_namespace and -undefined dynamic_lookup to the "Other Linker Flags" (a.k.a. OTHER_LDFLAGS). The flat namespace lets the symbols be found in the test harness when the plugin is loaded. The undefined dynamic_lookup means to suppress warnings about undefined symbols. This could conceivably mask errors, but it's no worse than ZeroLink.

In the Xcode project for the test harness

Add usefulStuff.c, and turn on the "Preserve Private External Symbols" checkbox (a.k.a -keep_private_externs). That turns the symbol BWDebugLog (and others) into exported symbols that'll be visible to the plugin. Otherwise the plugin will never get past that != NULL check earlier.

Once all that's done, my plugin loads into the test harness and can get controlled. It can be loaded into the Real App without undefined symbol errors.

borkware home | products | miniblog | rants | quickies | cocoaheads
Advanced Mac OS X Programming book