Nim bindings for libimobiledevice – the cross-platform library that talks to iOS devices.
Upstream: https://github.com/libimobiledevice/libimobiledevice
- Complete low-level coverage – 28 headers, 332 functions in
src/imobiledevice/bindings/(afc,lockdown,installation_proxy,diagnostics_relay,house_arrest,file_relay,sbservices,heartbeat,screenshotr,debugserver,mobile_image_mounter,misagent,mobileactivation,webinspector,bt_packet_logger,companion_proxy,reverse_proxy,syslog_relay,ostrace,preboard,restore,service,property_list_service,mobilebackup/mobilebackup2,mobilesync,notification_proxyand corelibimobiledevice.h)- C-style naming preserved,
{.push importc, header: "<libimobiledevice/...>" .}/{.pop.}pragmas - Opaque structs as
incompleteStruct, enums with exact C values,cstringArray(system/ctypes.nim) helpers - Links with
-limobiledevice -lplistvia{.passL.}
- C-style naming preserved,
- High-level idiomatic API directly in
src/imobiledevice/*.nim(plus optional subdirs, not all in one subdir) –device,lockdown_client,afc_client,installation_proxy_client,diagnostics_relay_client,house_arrest_client,file_relay_client, etc.Device/Connection/*Clientasref objectwith=destroy/closeRAIIseq[string]instead ofchar**,Plist(src/imobiledevice/plist.nim) forplist_t,string/uint64handles- Exceptions (
errors.nim:MobileDeviceError,IdeviceError,LockdownError,AfcError…) via*_strerror utils.nimusescstringArray,cstringArrayToSeq,allocCStringArray/deallocCStringArrayfromsystem.nim- Every high-level proc carries
##doc comments inside the body
- Plist helper –
src/imobiledevice/plist.nimwrapsplist_tfrom<plist/plist.h>(newPlist,borrow,takeOwnership,toXml/fromXml,dictSetString/dictGetString)
- Nim >= 2.2.10
libimobiledeviceandlibplistdevelopment packages- macOS:
brew install libimobiledevice libplist - Debian/Ubuntu:
apt install libimobiledevice-dev libplist-dev - From source: https://github.com/libimobiledevice/libimobiledevice
- macOS:
nimble install imobiledeviceOr for local development:
nimble install --depsOnlyAll high-level modules live directly in src/imobiledevice/*.nim and are importable as import imobiledevice/device.
import imobiledevice/device
let devices = listDevices()
echo devices # @["00008030-00123456789ABC"]
if devices.len > 0:
let dev = newDevice(devices[0])
defer: dev.close()
echo dev.getUdid()
echo dev.getVersion() # (major, minor, patch)
echo dev.versionAtLeast(17, 0, 0)
echo libVersion()import imobiledevice/device
import imobiledevice/lockdown_client
import imobiledevice/plist
let dev = newDevice("00008030-00123456789ABC")
let lockdown = newLockdownClient(dev)
defer: lockdown.close()
echo lockdown.getDeviceName()
echo lockdown.getDeviceUdid()
echo lockdown.getSyncDataClasses()
let info = lockdown.getValue("", "DeviceName")
echo info.toXml()
let svc = lockdown.startService("com.apple.afc")
echo svc.port, svc.sslEnabledimport imobiledevice/device
import imobiledevice/afc_client
let dev = newDevice("00008030-00123456789ABC")
let afc = newAfcClient(dev)
defer: afc.close()
for entry in afc.readDirectory("/"):
echo entry
echo afc.getDeviceInfoValue("FSTotalBytes")
let h = afc.openFile("/test.txt", AFC_FOPEN_RDONLY)
defer: afc.closeFile(h)
echo afc.read(h, 1024)
afc.makeDirectory("/MyDir")
afc.removePath("/MyDir")import imobiledevice/device
import imobiledevice/installation_proxy_client
import imobiledevice/plist
let dev = newDevice("00008030-00123456789ABC")
let inst = newInstallationProxyClient(dev)
defer: inst.close()
var opts = newDict() # empty plist dict
var res: plist_t
inst.lookup(nil, opts.raw, addr res) # low-level still accessible
# High-level browse returns via plist, convert with plist helpersimport imobiledevice/device
import imobiledevice/diagnostics_relay_client
import imobiledevice/house_arrest_client
import imobiledevice/file_relay_client
let dev = newDevice("00008030-00123456789ABC")
let diag = newDiagnosticsRelayClient(dev)
defer: diag.close()
# diag.requestDiagnostics("All", ...)
let har = newHouseArrestClient(dev)
# har.sendCommand("VendDocuments", "com.example.app")Direct C API remains available via src/imobiledevice/bindings/:
import imobiledevice/bindings/libimobiledevice
import imobiledevice/bindings/afc
import imobiledevice/bindings/lockdown
var dev: idevice_t
if idevice_new(addr dev, "00008030-00123456789ABC".cstring) == IDEVICE_E_SUCCESS:
defer: discard idevice_free(dev)
var afc: afc_client_t
if afc_client_start_service(dev, addr afc, "mobiledevice".cstring) == AFC_E_SUCCESS:
defer: discard afc_client_free(afc)
var list: cstringArray
discard afc_read_directory(afc, "/".cstring, cast[ptr ptr cstring](addr list))
for s in cStringArrayToSeq(list):
echo s
discard afc_dictionary_free(cast[ptr cstring](list))Low-level uses {.push importc, header: "<libimobiledevice/afc.h>" .} and incompleteStruct as in the reference libevent-nim example, with exact C error values (-256 for unknown, 1 | 4 for lock flags, etc.).
src/imobiledevice.nim # re-exports bindings + high-level core
src/imobiledevice/
bindings/ # 28 low-level C bindings
device.nim # high-level Device / Connection
errors.nim # MobileDeviceError hierarchy
plist.nim # Plist ref wrapper
utils.nim # cstringArray helpers (system.nim)
lockdown_client.nim
afc_client.nim
installation_proxy_client.nim
... (25 service clients directly in src/imobiledevice/*.nim)
reference/include/libimobiledevice # vendored C headers
High-level lives directly in src/imobiledevice/*.nim (and optional subdirs like src/imobiledevice/bindings/ for low-level), not all isolated in a single highlevel/ directory.
Generate with nim doc src/imobiledevice.nim or nimble doc.
MIT – see LICENSE.
Upstream libimobiledevice is LGPL-2.1 – see https://github.com/libimobiledevice/libimobiledevice.