【问题标题】:Conditionally compiling for differences in libxml2 in iOS 7有条件地编译 iOS 7 中 libxml2 的差异
【发布时间】:2013-09-24 11:53:19
【问题描述】:

在使用 iOS 7 SDK 时,由于 libxml2 中的更改,我不得不更改库的一行以使用新的输出缓冲区访问器方法用于 xmloutput 缓冲区。

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

导致编译错误“struct_xmlBuf 类型的定义不完整”。使用新的访问器方法变成:

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

这工作正常,但是当在 iOS 6 上运行时,对于提到 libxml2.2.dylib 的新方法,它会因“惰性符号绑定失败:未找到符号”而崩溃,这并不奇怪。

您如何有条件地进行此更改,以使用基本 SDK iOS 7 进行编译并仍可在 iOS 5、6 和 7 上运行?

注意:像其他问题一样,通常在运行时检查 iOS 版本是不够的,因为旧行不再编译。

我一直在尝试和考虑:

  • 检查xmlOutputBufferGetContent != NULL,始终正确
  • 使用 libxml2.2 代替 libxml2
  • 检查LIBXML_DOTTED_VERSION,总是2.9.0
  • 检查 LIBXML2_NEW_BUFFER 定义的新方法,始终正确

所有这些都导致在编译之前或之后总是只选择一行,主要基于 SDK。在非 iOS 项目(谷歌搜索)中处理这一变化的其他少数人似乎总是针对一个版本的 libxml 进行编译。

【问题讨论】:

    标签: ios objective-c ios7 libxml2


    【解决方案1】:

    类似下面的东西应该可以工作:

    #include <dlfcn.h>
    
    typedef const xmlChar *(*getContent_t)(xmlOutputBufferPtr out);
    typedef size_t (*getSize_t)(xmlOutputBufferPtr out);
    

    然后:

    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)];
    }
    

    对于旧版本的 libxml2(2.9.0 之前),使用旧的缓冲区结构。对于较新的版本,使用dlsym 搜索新的访问器。缓存dlsym返回的函数指针会提高性能。

    【讨论】:

    • 我刚刚逐步添加了它并且它可以工作(autorelease 需要为 ARC 删除)。 if true 结果中的代码实际上完全独立工作,因为强制转换或单个-&gt; 似乎可以防止原始编译错误。我将 else 代码替换为直接使用推荐的输出访问器方法,因为我不需要向后 SDK 兼容性,但这很有用。
    猜你喜欢
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    • 2020-10-16
    相关资源
    最近更新 更多