summaryrefslogtreecommitdiff
path: root/src/examples/gen_ctypes.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/examples/gen_ctypes.py')
-rw-r--r--src/examples/gen_ctypes.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/examples/gen_ctypes.py b/src/examples/gen_ctypes.py
new file mode 100644
index 0000000..0fb62e4
--- /dev/null
+++ b/src/examples/gen_ctypes.py
@@ -0,0 +1,167 @@
+from pyparsing import *
+
+typemap = {
+ "byte" : "c_byte",
+ "char" : "c_char",
+ "char *" : "c_char_p",
+ "double" : "c_double",
+ "float" : "c_float",
+ "int" : "c_int",
+ "int16" : "c_int16",
+ "int32" : "c_int32",
+ "int64" : "c_int64",
+ "int8" : "c_int8",
+ "long" : "c_long",
+ "longlong" : "c_longlong",
+ "short" : "c_short",
+ "size_t" : "c_size_t",
+ "ubyte" : "c_ubyte",
+ "uchar" : "c_ubyte",
+ "u_char" : "c_ubyte",
+ "uint" : "c_uint",
+ "u_int" : "c_uint",
+ "uint16" : "c_uint16",
+ "uint32" : "c_uint32",
+ "uint64" : "c_uint64",
+ "uint8" : "c_uint8",
+ "u_long" : "c_ulong",
+ "ulong" : "c_ulong",
+ "ulonglong" : "c_ulonglong",
+ "ushort" : "c_ushort",
+ "u_short" : "c_ushort",
+ "void *" : "c_void_p",
+ "voidp" : "c_voidp",
+ "wchar" : "c_wchar",
+ "wchar *" : "c_wchar_p",
+ "Bool" : "c_bool",
+ "void" : "None",
+ }
+
+LPAR,RPAR,LBRACE,RBRACE,COMMA,SEMI = map(Suppress,"(){},;")
+ident = Word(alphas, alphanums + "_")
+integer = Regex(r"[+-]?\d+")
+hexinteger = Regex(r"0x[0-9a-fA-F]+")
+
+const = Suppress("const")
+primitiveType = oneOf(t for t in typemap if not t.endswith("*"))
+structType = Suppress("struct") + ident
+vartype = (Optional(const) +
+ (primitiveType | structType | ident) +
+ Optional(Word("*")("ptr")))
+def normalizetype(t):
+ if isinstance(t, ParseResults):
+ return ' '.join(t)
+ #~ ret = ParseResults([' '.join(t)])
+ #~ return ret
+
+vartype.setParseAction(normalizetype)
+
+arg = Group(vartype("argtype") + Optional(ident("argname")))
+func_def = (vartype("fn_type") + ident("fn_name") +
+ LPAR + Optional(delimitedList(arg|"..."))("fn_args") + RPAR + SEMI)
+def derivefields(t):
+ if t.fn_args and t.fn_args[-1] == "...":
+ t["varargs"]=True
+func_def.setParseAction(derivefields)
+
+fn_typedef = "typedef" + func_def
+var_typedef = "typedef" + primitiveType("primType") + ident("name") + SEMI
+
+enum_def = (Keyword("enum") + LBRACE +
+ delimitedList(Group(ident("name") + '=' + (hexinteger|integer)("value")))("evalues")
+ + Optional(COMMA)
+ + RBRACE)
+
+c_header = open("snmp_api.h").read()
+
+
+module = "pynetsnmp"
+
+user_defined_types = set()
+typedefs = []
+fn_typedefs = []
+functions = []
+enum_constants = []
+
+# add structures commonly included from std lib headers
+def addStdType(t,namespace=""):
+ fullname = namespace+'_'+t if namespace else t
+ typemap[t] = fullname
+ user_defined_types.add(t)
+addStdType("fd_set", "sys_select")
+addStdType("timeval", "sys_time")
+
+def getUDType(typestr):
+ key = typestr.rstrip(" *")
+ if key not in typemap:
+ user_defined_types.add(key)
+ typemap[key] = "%s_%s" % (module, key)
+
+def typeAsCtypes(typestr):
+ if typestr in typemap:
+ return typemap[typestr]
+ if typestr.endswith("*"):
+ return "POINTER(%s)" % typeAsCtypes(typestr.rstrip(" *"))
+ return typestr
+
+# scan input header text for primitive typedefs
+for td,_,_ in var_typedef.scanString(c_header):
+ typedefs.append( (td.name, td.primType) )
+ # add typedef type to typemap to map to itself
+ typemap[td.name] = td.name
+
+# scan input header text for function typedefs
+fn_typedefs = fn_typedef.searchString(c_header)
+# add each function typedef to typemap to map to itself
+for fntd in fn_typedefs:
+ typemap[fntd.fn_name] = fntd.fn_name
+
+# scan input header text, and keep running list of user-defined types
+for fn,_,_ in (cStyleComment.suppress() | fn_typedef.suppress() | func_def).scanString(c_header):
+ if not fn: continue
+ getUDType(fn.fn_type)
+ for arg in fn.fn_args:
+ if arg != "...":
+ if arg.argtype not in typemap:
+ getUDType(arg.argtype)
+ functions.append(fn)
+
+# scan input header text for enums
+enum_def.ignore(cppStyleComment)
+for en_,_,_ in enum_def.scanString(c_header):
+ for ev in en_.evalues:
+ enum_constants.append( (ev.name, ev.value) )
+
+print "from ctypes import *"
+print "%s = CDLL('%s.dll')" % (module, module)
+print
+print "# user defined types"
+for tdname,tdtyp in typedefs:
+ print "%s = %s" % (tdname, typemap[tdtyp])
+for fntd in fn_typedefs:
+ print "%s = CFUNCTYPE(%s)" % (fntd.fn_name,
+ ',\n '.join(typeAsCtypes(a.argtype) for a in fntd.fn_args))
+for udtype in user_defined_types:
+ print "class %s(Structure): pass" % typemap[udtype]
+
+print
+print "# constant definitions"
+for en,ev in enum_constants:
+ print "%s = %s" % (en,ev)
+
+print
+print "# functions"
+for fn in functions:
+ prefix = "%s.%s" % (module, fn.fn_name)
+
+ print "%s.restype = %s" % (prefix, typeAsCtypes(fn.fn_type))
+ if fn.varargs:
+ print "# warning - %s takes variable argument list" % prefix
+ del fn.fn_args[-1]
+
+ if fn.fn_args.asList() != [['void']]:
+ print "%s.argtypes = (%s,)" % (prefix, ','.join(typeAsCtypes(a.argtype) for a in fn.fn_args))
+ else:
+ print "%s.argtypes = ()" % (prefix)
+
+