【问题标题】:Is There A Swift preprocessor Way to Detect Bridging Header Includes?是否有一种 Swift 预处理器方法来检测桥接头包含?
【发布时间】:2019-04-11 18:53:11
【问题描述】:

我找到的唯一答案是在this,我对此并不满意。

我正在添加一个标准 MD5 转换器作为字符串扩展:

/* ###################################################################################################################################### */
/**
 From here: https://stackoverflow.com/q/24123518/879365
 I am not making this public, because it requires the common crypto in the bridging header.
 */
fileprivate extension String {
    /* ################################################################## */
    /**
     - returns: the String, as an MD5 hash.
     */
    var md5: String {
        let str = self.cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(self.lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(str!, strLen, result)

        let hash = NSMutableString()

        for i in 0..<digestLen {
            hash.appendFormat("%02x", result[i])
        }

        result.deallocate()
        return hash as String
    }
}

它要求我将以下内容添加到我的桥接头中:

#import <CommonCrypto/CommonCrypto.h>

由于我想将此添加到一套可重复使用的工具中,我想看看是否有一种方法可以在编译时检测是否使用了通用加密库。

有没有办法将其设置为条件编译?

如果不是,这没什么大不了的;只是意味着我需要将其设置为单独的源文件。

【问题讨论】:

    标签: swift string commoncrypto


    【解决方案1】:

    值得注意的是,如果您使用dlsym 访问它,您可以在没有桥接头的情况下调用CC_MD5

    import Foundation
    
    typealias CC_MD5_Type = @convention(c) (UnsafeRawPointer, UInt32, UnsafeMutableRawPointer) -> UnsafeMutableRawPointer
    
    let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
    let CC_MD5 = unsafeBitCast(dlsym(RTLD_DEFAULT, "CC_MD5")!, to: CC_MD5_Type.self)
    
    var md5 = Data(count: 16)
    md5.withUnsafeMutableBytes {
        _ = CC_MD5("abc", 3, $0)
    }
    
    assert(md5 == Data(bytes: [0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72]))
    

    【讨论】:

    • 更好!我为此给你一张绿卡!谢谢!我正在使用解决方案代码修改我的原始问题。其实我记得,但是忘记了。谢谢!
    • @Rift 请不要在您的问题中编辑答案;我已经回滚了你上次的编辑。如果您想分享您的解决方案,请在答案框中发布答案。如果您想将功劳归功于 Rob,您仍然可以继续将 Rob 的答案标记为已接受。
    • 会的。我不想从他那里拿走。
    【解决方案2】:

    这是我找到的解决方案。这是我原始变体的混搭,也是 Rob 的出色答案。它很有魅力(我用它来建立对RFC2617 Digest authentication的响应)。由于使用了内置的钩子,我不再需要桥接头,并且可以将它添加到我的字符串扩展集中。

    非常经典的正确答案案例来自与我正在寻找的完全不同的地方。当这种情况发生时,我喜欢它。

    来吧:

    public extension String {
        /* ################################################################## */
        /**
         From here: https://stackoverflow.com/q/24123518/879365, but modified from here: https://stackoverflow.com/a/55639723/879365
         - returns: an MD5 hash of the String
         */
        var md5: String {
            var hash = ""
            
            // Start by getting a C-style string of our string as UTF-8.
            if let str = self.cString(using: .utf8) {
                // This is a cast for the MD5 function. The convention attribute just says that it's a "raw" C function.
                typealias CC_MD5_Type = @convention(c) (UnsafeRawPointer, UInt32, UnsafeMutableRawPointer) -> UnsafeMutableRawPointer
                
                // This is a flag, telling the name lookup to happen in the global scope. No dlopen required.
                let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
                
                // This loads a function pointer with the CommonCrypto MD5 function.
                let CC_MD5 = unsafeBitCast(dlsym(RTLD_DEFAULT, "CC_MD5")!, to: CC_MD5_Type.self)
                
                // This is the length of the hash
                let CC_MD5_DIGEST_LENGTH = 16
                
                // This is where our MD5 hash goes. It's a simple 16-byte buffer.
                let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: CC_MD5_DIGEST_LENGTH)
                
                // Execute the MD5 hash. Save the result in our buffer.
                _ = CC_MD5(str, CUnsignedInt(str.count), result)
                
                // Turn it into a normal Swift String of hex digits.
                for i in 0..<CC_MD5_DIGEST_LENGTH {
                    hash.append(String(format: "%02x", result[i]))
                }
                
                // Don't need this anymore.
                result.deallocate()
            }
            
            return hash
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-23
      • 2023-01-23
      • 1970-01-01
      • 2017-04-21
      相关资源
      最近更新 更多