iopc backends: C, JSON, TypeScript, Python stubs
iopc -l <langs> selects one or more code generators. This page
documents what each emits. The C type mapping itself is on a dedicated
page (C language mapping).
1. C backend (-l c)
Four files per package (user code includes only <pkg>.iop.h):
<pkg>-tdef.iop.h-
The forward-declaration header: full C
enumdefinitions (with_count/_min/_maxmacros and alias constants), forwardtypedef struct pkgnamet …plus array/optional typedefs for every type. Other packages include it for weak dependencies — this is what breaks cross-package cycles. <pkg>-t.iop.h-
The data-layout header: the actual
structdefinitions (fields possibly reordered to reduce padding unless@noReorder), class id macros, union tag enums and accessor macros, and theEXPORTdeclarations of the type descriptors (…s,…e). Includes the-tdef.iop.hof weak dependencies and the-t.iop.hof strong ones. <pkg>.iop.h-
The interface header: RPC argument/result/exception struct types, per-RPC tag/async macros, interface (
…if) and module (…mod) descriptors, typedef descriptors and the package descriptor (pkg__pkg). <pkg>.iop.c-
The reflection data: field tables, default values, constraint check functions, attribute tables, class tables, RPC/interface/module descriptors and the
iop_pkg_twith its dependency list.
--c-resolve-includes replaces package-path includes
(#include "a/b/c-t.iop.h") with relative includes computed in the
source tree (#include "../../other/pkg.iop.h"); it is incompatible
with an output directory.
2. JSON backend (-l json)
Emits a machine-readable description of the package — the input format consumed by the TypeScript/Backbone runtime and other tooling. One tab-indented JSON object per package:
{
"name": "pkg",
"help": { "brief": "…", "details": "…" },
"objects": [ … ],
"interfaces": [ … ],
"modules": [ … ]
}
-
objectslists, in order: enums, then structs/unions/classes, then typedefs, then the anonymous RPC argument/result/exception structs (namedpkg.Iface.funArgs/…Res/…Exn). -
Cross-package references appear inline as fully-qualified names (
"other.pkg.Type"); there is no dependency list. -
Every object carries
name,fullName, atypediscriminant ("enum","struct","union","class","typedef","snmpObj","snmpTbl","snmpIface"), and optionallyhelp(keysbrief,details,warning, plusexampleas raw JSON) andgenAttrs(object keyed by generic-attribute name, values{"type": "string"|"int"|"double"|"boolean"|"object", "value": …}).
Per kind:
- Enums
-
values— object keyed by value name withvalue(int), optionalaliases(array) andgenAttrs;valuesHelpfor documented values;constraints: {"strict": true}for@strict. The C@prefixis not exported. - Structs/unions/classes
-
fields— object keyed by field name; each field hastype(scalar name — note"boolean","number"for double,"data"for bytes — or a fully-qualified type name), at most one ofdefault,optional: true,repeated: true(mandatory fields carry none; 64-bit defaults beyond 253 are emitted as strings), optionalhelp,constraints(keysmin,max,minOccurs,maxOccurs,minLength,maxLength,length,cdata,nonEmpty,nonZero,pattern,allow/disallowarrays),genAttrs,private: true,deprecated: true. Field tags are not emitted. Classes addparent,isAbstract,private, andstatics(object of static fields with theirdefault); the numeric class id is not emitted. - Typedefs
-
a
typedefkey holding the aliased type, plusconstraintsandgenAttrs. - Interfaces
-
rpcs— object keyed by RPC name; each RPC has optionalin,out,throw(omitted whenvoid; either an anonymous-struct fullname or an existing type name, withinHelp/outHelp/throwHelpcarrying the referenced type’s doc),async: trueforout null,help,genAttrs. - Modules
-
optional
parentarray (multiple inheritance) andinterfaceskeyed by instance name withtypeandhelp; members inherited from parents are not repeated.
Private elements are included and flagged private: true, not
skipped.
3. TypeScript backend (-l typescript)
Generates an ES module per package:
-
dependencies are imported as
import * as abc from "iop/a/b/c.iop";and referenced asabc.Type; -
enums become three aliases:
Foo_Int(numeric literal union),Foo_Str(name literal union) andFoo = Foo_Str; -
structs/classes become
export interface Foo { … }; classesextendtheir parent and root classes carry a_class: stringdiscriminant. Scalars map tonumber(long/ulong:number | string),boolean,string,nullfor void; optional fields get?; repeated fields areArray<T>; -
unions become
export type U = { a: T1 } | { b: T2 }plusU_Pairs({kind, value}form) andU_Keys; -
interfaces/RPCs are grouped under
export namespace interfaces: per RPC,funArgs/funRes/funExntypes and afunIcQuerycall-signature type — anicQuery-style call(rpc, args, options?) ⇒ JQueryDeferred<funRes>; each interface aggregates its RPCs into a combinedIcQuerytype; -
only typedefs pointing at another package are emitted, as type re-exports.
The module also imports the JSON backend output (import JSON from
'json/<pkg>.iop.json') and generates Backbone model classes
(Foo_Model extends StructModel/ClassModel/UnionModel, Foo_Collection
extends IopCollection) with registration calls; models expose the
icQuery fields wiring their RPCs to the runtime. This is always
emitted — the former --typescript-enable-backbone opt-in no longer
exists. @typescriptNoCollection suppresses the collection class for a
type; @forceFieldName names are emitted verbatim.
4. Python stub backend (-l pystub)
Emits PEP 484 type stubs (.pyi) that give a static type checker
(mypy, pyright, …) full knowledge of the classes
IOPy materialises at runtime — the runtime keeps
building them dynamically; these stubs only describe them.
One file per package, all written flat into --pystub-output-path
(no directory hierarchy). The module name joins the package-path
components with _ and appends _iop (package foo.bar →
foo_bar__iop.pyi). Every declaration is decorated
@typing.type_check_only; the file imports the hand-written base stub
iopy (src/iopy/iopy.pyi), which defines iopy.Struct,
iopy.Union, iopy.Enum, iopy.RPC, the channel classes and helpers
such as IcKwargs.
Per kind:
- Enums
-
class Foo(iopy.Enum): …. - Structs/classes
-
class Foo(iopy.Struct)(a child class extends its parent class instead). Fields become annotated attributes — scalars map toint(all integer widths),float(double),bool,str(string/xml),bytes(data); an enum field is astr(the value name);voidistyping.Any. Optional fields areiopy.IopOptField[T], repeated fieldslist[T]. Alongside the class,TypedDict`s describe the field mappings — a strict `Foo_DictType(theto_dict()output) and a wideFoo_ParamDictType(constructor kwargs, where optionals also acceptNone) — andFoo_ParamTypeunions the class with those dicts.initandto_dict()get typed `@typing.overload`s. - Unions
-
class Foo(iopy.Union)with a per-memberTypedDictand overloadedinit, plus aFoo_UnambiguousTypealias listing the member value types that identify a member without ambiguity. - Interfaces/modules/RPCs
-
each RPC yields
Foo_Arg/Foo_Res/Foo_Exntypes and aniopy.RPC[…]subclass with typed synchronous andasynccall overloads merging the argument dict withiopy.IcKwargs; interfaces, modules, the channel and the package become the correspondingly typed classes.