Conditionally compiling for differences in libxml2 in iOS 7

一世执手 提交于 2019-12-23 21:44:44

问题


When using iOS 7 SDK, due to changes in libxml2 I had to change a single line of a library to use the new output buffer accessor methods for the xmloutput buffer.

NSData * result = [[[NSData alloc] initWithBytes:outputBuffer->buffer->content 
                                  length:outputBuffer->buffer->use] autorelease];

Resulted in compile error 'Incomplete definition of type struct_xmlBuf'. Using the new accessor methods this became:

NSData * result = [[NSData alloc] initWithBytes:xmlOutputBufferGetContent(outputBuffer)
                                  length:xmlOutputBufferGetSize(outputBuffer)];

This works fine but when run on iOS 6 it not surprisingly crashes with 'lazy symbol binding failed: Symbol not found' for the new methods with mentions of libxml2.2.dylib.

How can you do this change conditionally in a way which will compile with base SDK iOS 7 and still run on iOS 5, 6 & 7?

Note: The usual checking iOS version at runtime like other problems is insufficient as the old line no longer compiles.

I have been trying and considering:

  • Checking xmlOutputBufferGetContent != NULL, always true
  • Using libxml2.2 instead of libxml2
  • Checking LIBXML_DOTTED_VERSION, always 2.9.0
  • Checking for LIBXML2_NEW_BUFFER new methods defined, always true

All of these result in only one line always being chosen before or after compilation, largely based on the SDK. The few other people dealing with this change in non-iOS projects (Googling) appear to be always compiling targeting one version of libxml.


回答1:


Something like following should work:

#include <dlfcn.h>

typedef const xmlChar *(*getContent_t)(xmlOutputBufferPtr out);
typedef size_t (*getSize_t)(xmlOutputBufferPtr out);

Then:

int libxmlVersion = atoi(xmlParserVersion);

if (libxmlVersion < 20900) {
    xmlBufferPtr oldStyleBuffer = (xmlBufferPtr)outputBuffer->buffer;
    NSData * result = [[[NSData alloc] initWithBytes:oldStyleBuffer->content 
                              length:oldStyleBuffer->use] autorelease];
}
else {
    getContent_t getContent = dlsym(RTLD_DEFAULT, "xmlOutputBufferGetContent");
    getSize_t getSize = dlsym(RTLD_DEFAULT, "xmlOutputBufferGetSize");
    NSData * result = [[NSData alloc] initWithBytes:getContent(outputBuffer)
                              length:getSize(outputBuffer)];
}

For older versions of libxml2 (before 2.9.0), the old buffer struct is used. For newer versions, the new accessors are searched using dlsym. Caching the function pointers returned by dlsym will improve performance.



来源:https://stackoverflow.com/questions/18893959/conditionally-compiling-for-differences-in-libxml2-in-ios-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!