views:

39

answers:

2

I have a project that needs to incorporate two third-party libraries, libA and libB. I have little, if any, influence over the third-party libraries. The problem being is that both libA and libB include different versions of a common library, ASIHTTPRequest. As a result, I'm getting errors like:

-[ASIFormDataRequest setNumberOfTimesToRetryOnTimeout:]: unrecognized selector sent to instance 0x3b4170

, which I can only assume are because libA is referring to libB's implementation of ASIHTTPRequest (or the other way around).

I've tried playing around with strip -s <symbol file> -u <library> to isolate the libraries' symbols from each other, but that results in XCode's linker spitting out thousands of warnings and doesn't actually fix the main problem outlined above.

ld: warning: can't add line info to anonymous symbol anon-func-0x0 from ...

In general, how can/should one isolate libraries from each other?

A: 

There is absolutely no way to do so. One Objective-C application can have only one meaning for one symbol at a time. If you load two different versions of one library the last one will overwrite the first one.

Two workarounds:

  1. convince the developer to use a recent version
  2. run both libraries in separate processes
Max Seelemann
A: 

If they used the same linker symbol name for different routines, the only way out (short of hacking their object files), is to link them into different executables somehow.

On platforms that support dynamic linking (eg: DLLs) you could build one or both into a separate DLL. If they aren't part of the exported interface the symbols shouldn't clash then.

Otherwise you would be stuck putting them into entirely separate processes and using IPC to pass data between them.

T.E.D.
The problem is that in Objective-C there are no hidden symbols. If both libraries refer to a common third Obj-C library, these symbols are always visible and hence conflict. separate processes are the only way to avoid these issues.
Max Seelemann
@Max Seelemann - I don't think it really matters. Typically symbols tucked away in dynamically-loaded libraries like DLLs are not visible to other DLLs or to the main program. I've used this in the past to allow libraries that used conflicting names for internal subroutines and global variables (and were intended to run in different processes) to play nice with each other in the same executable.
T.E.D.
That might be fairly right. But Objective-C has a central registry for method names, the runtime, no matter where they come from. There is no way to hide or export a symbol in objc. All symbols are always public.
Max Seelemann
@Max Seelemann - I'd have to see that in action. There's a good chance the "central registry" of the DLL is separate as well.
T.E.D.
No way. There only is one. Objective-C dispatches ALL method calls through a single function, objc_msgSend. All methods must be visible to this single method, and hence there can only be a single registry. There is no context or call site information, only a method name and a class. Loading a class in two different versions will result in only one existing. And hence there is only one version of the library available to the runtime, even though the symbols have been loaded twice.
Max Seelemann
Thanks for the responses (and thread). Enlightening. Unfortunately, I can't use two processes as this problem pertains to an iPhone application. Time to start fighting with the library providers...
D Carney
Yeah, sounds like you are stuck banging on them to update to using the same library. This is why I don't like depending on code that isn't either developed in-house or OpenSource.
T.E.D.