Thanks @Araq for your help. I found the `signatureHash` macro by investigating how symbol names are generated, and tried using it to create stable hashes of types across my DLLs, but for some reason it would sometimes generate a different hash for the same type used in different DLLs. I saw this PR which might help, but I'm unsure if it does what I think it does: <https://github.com/nim-lang/Nim/pull/13305>.
For now I ended up going with something similar to @enthus1ast's suggestion. Below is the PoC implementation. It generates sequential IDs based on a string hash of a type. It can be used across multiple DLL boundaries by assigning memory to `typeRegistry.hashes` allocated by the main executable. import std/macros type TypeId* = uint16 TypeRegistry* = object hashes: ptr[TypeHashArray] TypeHashArray = array[TypeId.high, TypeHash] TypeHash = array[32, char] proc init*(self: var TypeRegistry) {.ctor.} = self.hashes = createShared TypeHashArray proc deinit*(self: var TypeRegistry) = if self.hashes != nil: dealloc self.hashes self.hashes = nil var typeRegistry*: TypeRegistry proc setTypeRegistry*(registry: TypeRegistry) {.dllapi.} = typeRegistry = registry proc getTypeHash(hash: string): TypeHash {.compileTime.} = for i, element in enumerate hash: result[i] = element macro typeHash(Type: type): TypeHash = # TODO: Make this more reliable (`signatureHash` fails sometimes) # Wait for https://github.com/nim-lang/Nim/pull/13305 newCall(bindSym"getTypeHash", newLit $Type.getTypeImpl[1]) proc getId(typeHash: static[TypeHash]): TypeId {.noinit.} = var id: TypeId while (let hash = typeRegistry.hashes[id] ; hash[0] != '\0'): if hash == typeHash: return id id += 1 typeRegistry.hashes[id] = typeHash return id # fast memoized type ID; doesn't use `Tables` proc typeId*(Type: type): TypeId {.noinit.} = var typeId {.global.} : TypeId var implId {.global.} = 0 var impl {.global.} = [ proc: TypeId {.inline noinit.} = typeId = getId Type.typeHash result = typeId implId += 1, proc: TypeId {.inline noinit.} = typeId ] result = impl[implId]() Run I hope someone finds something useful in that.