澄清:您的 C 代码(以及下面的 Swift 版本)检查是否
该程序运行在调试器控制,如果它正在运行,则不会
Xcode。可以在 Xcode 之外调试程序(通过调用 lldb 或
直接 gdb),并且可以从 Xcode 运行程序而无需调试它
(如果方案设置中的“调试可执行文件”复选框处于关闭状态)。
您可以简单地保留 C 函数并从 Swift 调用它。
中给出的食谱如何从 Swift 调用 Objective-C 代码? https://stackoverflow.com/questions/24002369/how-to-call-objective-c-code-from-swift也适用于纯 C 代码。
但将该代码转换为 Swift 实际上并不太复杂:
func amIBeingDebugged() -> Bool {
// Buffer for "sysctl(...)" call's result.
var info = kinfo_proc()
// Counts buffer's size in bytes (like C/C++'s `sizeof`).
var size = MemoryLayout.stride(ofValue: info)
// Tells we want info about own process.
var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
// Call the API (and assert success).
let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
assert(junk == 0, "sysctl failed")
// Finally, checks if debugger's flag is present yet.
return (info.kp_proc.p_flag & P_TRACED) != 0
}
Swift 5 更新 (Xcode 10.7):
strideofValue
并且相关的功能已经不存在了,
他们已被取代MemoryLayout.stride(ofValue:)
.
Remarks:
-
kinfo_proc()
创建一个完全初始化的结构,其中包含所有内容
字段设置为零,因此设置info.kp_proc.p_flag = 0
没有必要。
- The C
int
类型是Int32
是斯威夫特。
-
sizeof(info)
从C代码必须是strideOfValue(info)
在 Swift 中包含结构填充。和sizeofValue(info)
对于 64 位设备,上述代码在模拟器中始终返回 false。这是最难弄清楚的部分。
斯威夫特2逻辑:
func amIBeingDebugged() -> Bool {
var info = kinfo_proc()
var mib : [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
var size = strideofValue(info)
let junk = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
assert(junk == 0, "sysctl failed")
return (info.kp_proc.p_flag & P_TRACED) != 0
}