我知道swift-demangle命令行实用程序。我正在寻找能让我从Swift本身做到的事情。
当我在Swift REPL中运行:target modules dump symtab
之后看到此内容时,我很兴奋,但我不知道如何拨打swift_demangleSimpleClass
。
似乎有一个@asmname
命令允许调用私有的Swift函数,但我还没有能够让它工作。
我可能最终会为此编写一个基于正则表达式的解析器,但在Swift框架中调用某些内容似乎更安全。
答案 0 :(得分:3)
func typename (thing:Any) -> String{
let name = _stdlib_getTypeName(thing)
let demangleName = _stdlib_demangleName(name)
return demangleName.componentsSeparatedByString(".").last!
}
答案 1 :(得分:3)
目前(XCode 6加7测试版)对于最高级别的课程,您只需获取您的appname加上一个点加上您的类名。所以它将类似MyApp.MyClass但是当你使用子类时,描述将在以下3个部分中构建:
这里的功能是一个特例。该描述还将提供有关函数签名的一些信息。
例如,您可以拥有_TtCFCC5MyApp7MyClass10MySubClass6myFuncFS0_FT_T_L_11MySubSubClass
这将是以下代码中MySubSubClass的描述:
class MyClass {
class MySubClass {
func myFunc() {
class MySubSubClass {
}
}
}
}
在这里,您可以找到一些sample code,它将该描述解析为易于使用的属性和数组。
更新:Demangle现在转换为swift。您可以在此处找到它:https://github.com/mattgallagher/CwlDemangle/blob/master/CwlDemangle/CwlDemangle.swift
答案 2 :(得分:2)
Swift 5
您可以使用 Swift 的 swift_demangle
函数来对名称进行解码,但默认情况下它不会导出,因此您需要先导入:
typealias Swift_Demangle = @convention(c) (_ mangledName: UnsafePointer<UInt8>?,
_ mangledNameLength: Int,
_ outputBuffer: UnsafeMutablePointer<UInt8>?,
_ outputBufferSize: UnsafeMutablePointer<Int>?,
_ flags: UInt32) -> UnsafeMutablePointer<Int8>?
func swift_demangle(_ mangled: String) -> String? {
let RTLD_DEFAULT = dlopen(nil, RTLD_NOW)
if let sym = dlsym(RTLD_DEFAULT, "swift_demangle") {
let f = unsafeBitCast(sym, to: Swift_Demangle.self)
if let cString = f(mangled, mangled.count, nil, nil, 0) {
defer { cString.deallocate() }
return String(cString: cString)
}
}
return nil
}
// How to use
if let s = swift_demangle("$s20MyPlayground_Sources4TestC4testSSyF") {
print(s) // MyPlayground_Sources.Test.test() -> Swift.String
}
答案 3 :(得分:-1)
更新:从XCode6 beta 5开始,NSStringFromClass似乎会自动返回demangled类名,因此不再需要此代码。
应该有一种内置的方法来做到这一点,但在此之前,这个扩展应该可以解决这个问题:
import Foundation
public func demangleClassName(mangled: String) -> String {
let scanner = NSScanner(string: mangled)
if (!scanner.scanString("_TtC", intoString: nil)) {
// not a mangled swift class name: Core Foundation, etc. have no module prefix
return mangled
}
var demangled = ""
var len : Int = 0
while (!scanner.atEnd && scanner.scanInteger(&len)) {
let range = Range(start:advance(mangled.startIndex, scanner.scanLocation), end: advance(mangled.startIndex, scanner.scanLocation + len))
let part = mangled.substringWithRange(range)
if (countElements(demangled) > 0) {
demangled += "."
}
demangled += part
scanner.scanLocation += len // skip to the next segment that may be prefixed by the number
}
return demangled
}
public extension NSObject {
/// demangle the current Swift object's class name, as per mangling description at: http://www.eswick.com/2014/06/inside-swift/
public class func demangledClassName() -> String {
return demangleClassName(className())
}
}