├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── autopxd └── __init__.py ├── setup.cfg ├── setup.py ├── test.py └── test ├── anonymous_enum.test ├── bar_baz.h ├── enum.test ├── forward_empty_struct.test ├── globals.test ├── inline_proto_nested.test ├── inline_proto_struct.test ├── nested.test ├── proto.test ├── struct.test ├── tux_foo.h ├── typedef.test ├── typedef_anonymous_enum.test ├── typedef_anonymous_struct.test ├── typedef_anonymous_union.test ├── typedef_enum.test ├── typedef_enum_alt.test ├── typedef_proto.test ├── typedef_struct.test ├── typedef_union.test ├── union.test └── whitelist.test /.gitignore: -------------------------------------------------------------------------------- 1 | autopxd/include/ 2 | *.egg-info/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: python 3 | 4 | python: 5 | - 2.7 6 | - 3.4 7 | 8 | install: pip install -e . 9 | 10 | script: ./test.py 11 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Thiago de Arruda 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### python-autopxd 2 | 3 | [![Build Status](https://travis-ci.org/tarruda/python-autopxd.svg?branch=master)](https://travis-ci.org/tarruda/python-autopxd) 4 | 5 | This module simplifies the task of exposing C libraries to cython by 6 | automatically generating .pxd files from C headers. 7 | 8 | #### Installation 9 | 10 | ``` 11 | pip install autopxd 12 | ``` 13 | 14 | #### Usage 15 | 16 | ``` 17 | autopxd HEADER_INPUT PXD_OUTPUT 18 | ``` 19 | -------------------------------------------------------------------------------- /autopxd/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import os.path 5 | import six 6 | import subprocess 7 | import sys 8 | 9 | import click 10 | from pycparser import c_parser, c_ast 11 | 12 | BUILTIN_HEADERS_DIR = os.path.join(os.path.dirname(__file__), 'include') 13 | # Types declared by pycparser fake headers that we should ignore 14 | IGNORE_DECLARATIONS = set(( 15 | 'size_t', '__builtin_va_list', '__gnuc_va_list', '__int8_t', '__uint8_t', 16 | '__int16_t', '__uint16_t', '__int_least16_t', '__uint_least16_t', 17 | '__int32_t', '__uint32_t', '__int64_t', '__uint64_t', '__int_least32_t', 18 | '__uint_least32_t', '__s8', '__u8', '__s16', '__u16', '__s32', '__u32', 19 | '__s64', '__u64', '_LOCK_T', '_LOCK_RECURSIVE_T', '_off_t', '__dev_t', 20 | '__uid_t', '__gid_t', '_off64_t', '_fpos_t', '_ssize_t', 'wint_t', 21 | '_mbstate_t', '_flock_t', '_iconv_t', '__ULong', '__FILE', 'ptrdiff_t', 22 | 'wchar_t', '__off_t', '__pid_t', '__loff_t', 'u_char', 'u_short', 'u_int', 23 | 'u_long', 'ushort', 'uint', 'clock_t', 'time_t', 'daddr_t', 'caddr_t', 24 | 'ino_t', 'off_t', 'dev_t', 'uid_t', 'gid_t', 'pid_t', 'key_t', 'ssize_t', 25 | 'mode_t', 'nlink_t', 'fd_mask', '_types_fd_set', 'clockid_t', 'timer_t', 26 | 'useconds_t', 'suseconds_t', 'FILE', 'fpos_t', 'cookie_read_function_t', 27 | 'cookie_write_function_t', 'cookie_seek_function_t', 28 | 'cookie_close_function_t', 'cookie_io_functions_t', 'div_t', 'ldiv_t', 29 | 'lldiv_t', 'sigset_t', '__sigset_t', '_sig_func_ptr', 'sig_atomic_t', 30 | '__tzrule_type', '__tzinfo_type', 'mbstate_t', 'sem_t', 'pthread_t', 31 | 'pthread_attr_t', 'pthread_mutex_t', 'pthread_mutexattr_t', 32 | 'pthread_cond_t', 'pthread_condattr_t', 'pthread_key_t', 'pthread_once_t', 33 | 'pthread_rwlock_t', 'pthread_rwlockattr_t', 'pthread_spinlock_t', 34 | 'pthread_barrier_t', 'pthread_barrierattr_t', 'jmp_buf', 'rlim_t', 35 | 'sa_family_t', 'sigjmp_buf', 'stack_t', 'siginfo_t', 'z_stream', 'int8_t', 36 | 'uint8_t', 'int16_t', 'uint16_t', 'int32_t', 'uint32_t', 'int64_t', 37 | 'uint64_t', 'int_least8_t', 'uint_least8_t', 'int_least16_t', 38 | 'uint_least16_t', 'int_least32_t', 'uint_least32_t', 'int_least64_t', 39 | 'uint_least64_t', 'int_fast8_t', 'uint_fast8_t', 'int_fast16_t', 40 | 'uint_fast16_t', 'int_fast32_t', 'uint_fast32_t', 'int_fast64_t', 41 | 'uint_fast64_t', 'intptr_t', 'uintptr_t', 'intmax_t', 'uintmax_t', 'bool', 42 | 'va_list', 43 | )) 44 | 45 | 46 | class PxdNode(object): 47 | indent = ' ' 48 | 49 | def __str__(self): 50 | return '\n'.join(self.lines()) 51 | 52 | 53 | class IdentifierType(PxdNode): 54 | def __init__(self, name, type_name): 55 | self.name = name or '' 56 | self.type_name = type_name 57 | 58 | def lines(self): 59 | if self.name: 60 | return ['{0} {1}'.format(self.type_name, self.name)] 61 | else: 62 | return [self.type_name] 63 | 64 | 65 | class Function(PxdNode): 66 | def __init__(self, return_type, name, args): 67 | self.return_type = return_type 68 | self.name = name 69 | self.args = args 70 | 71 | def argstr(self): 72 | l = [] 73 | for arg in self.args: 74 | lines = arg.lines() 75 | assert len(lines) == 1 76 | l.append(lines[0]) 77 | return ', '.join(l) 78 | 79 | def lines(self): 80 | return [ 81 | '{0} {1}({2})'.format(self.return_type, self.name, self.argstr()) 82 | ] 83 | 84 | 85 | class Ptr(IdentifierType): 86 | def __init__(self, node): 87 | self.node = node 88 | 89 | @property 90 | def name(self): 91 | return self.node.name 92 | 93 | @property 94 | def type_name(self): 95 | return self.node.type_name + '*' 96 | 97 | def lines(self): 98 | if isinstance(self.node, Function): 99 | f = self.node 100 | args = f.argstr() 101 | return ['{0} (*{1})({2})'.format(f.return_type, f.name, args)] 102 | else: 103 | return super(Ptr, self).lines() 104 | 105 | 106 | class Array(IdentifierType): 107 | def __init__(self, node): 108 | self.node = node 109 | 110 | @property 111 | def name(self): 112 | return self.node.name + '[1]' 113 | 114 | @property 115 | def type_name(self): 116 | return self.node.type_name 117 | 118 | 119 | class Type(PxdNode): 120 | def __init__(self, node): 121 | self.node = node 122 | 123 | def lines(self): 124 | lines = self.node.lines() 125 | lines[0] = 'ctypedef ' + lines[0] 126 | return lines 127 | 128 | 129 | class Block(PxdNode): 130 | def __init__(self, name, fields, kind): 131 | self.name = name 132 | self.fields = fields 133 | self.kind = kind 134 | 135 | def lines(self): 136 | rv = ['cdef {0} {1}:'.format(self.kind, self.name)] 137 | for field in self.fields: 138 | for line in field.lines(): 139 | rv.append(self.indent + line) 140 | return rv 141 | 142 | 143 | class Enum(PxdNode): 144 | def __init__(self, name, items): 145 | self.name = name 146 | self.items = items 147 | 148 | def lines(self): 149 | rv = [] 150 | if self.name: 151 | rv.append('cdef enum {0}:'.format(self.name)) 152 | else: 153 | rv.append('cdef enum:') 154 | for item in self.items: 155 | rv.append(self.indent + item) 156 | return rv 157 | 158 | 159 | class AutoPxd(c_ast.NodeVisitor, PxdNode): 160 | def __init__(self, hdrname): 161 | self.hdrname = hdrname 162 | self.decl_stack = [[]] 163 | self.visit_stack = [] 164 | 165 | def visit(self, node): 166 | self.visit_stack.append(node) 167 | rv = super(AutoPxd, self).visit(node) 168 | n = self.visit_stack.pop() 169 | assert n == node 170 | return rv 171 | 172 | def visit_IdentifierType(self, node): 173 | self.append(' '.join(node.names)) 174 | 175 | def visit_Block(self, node, kind): 176 | name = node.name 177 | if not name: 178 | name = self.path_name(kind[0]) 179 | if not node.decls: 180 | if self.child_of(c_ast.TypeDecl, -2): 181 | # not a definition, must be a reference 182 | self.append(name) 183 | return 184 | fields = self.collect(node) 185 | # add the struct/union definition to the top level 186 | self.decl_stack[0].append(Block(name, fields, kind)) 187 | if self.child_of(c_ast.TypeDecl, -2): 188 | # inline struct/union, add a reference to whatever name it was 189 | # defined on the top level 190 | self.append(name) 191 | 192 | def visit_Enum(self, node): 193 | items = [] 194 | if node.values: 195 | for item in node.values.enumerators: 196 | items.append(item.name) 197 | name = node.name 198 | type_decl = self.child_of(c_ast.TypeDecl, -2) 199 | if not name and type_decl: 200 | name = self.path_name('e') 201 | # add the enum definition to the top level 202 | if len(items): 203 | self.decl_stack[0].append(Enum(name, items)) 204 | if type_decl: 205 | self.append(name) 206 | 207 | def visit_Struct(self, node): 208 | return self.visit_Block(node, 'struct') 209 | 210 | def visit_Union(self, node): 211 | return self.visit_Block(node, 'union') 212 | 213 | def visit_TypeDecl(self, node): 214 | decls = self.collect(node) 215 | if not decls: 216 | return 217 | assert len(decls) == 1 218 | if isinstance(decls[0], six.string_types): 219 | self.append(IdentifierType(node.declname, decls[0])) 220 | else: 221 | self.append(decls[0]) 222 | 223 | def visit_Decl(self, node): 224 | decls = self.collect(node) 225 | if not decls: 226 | return 227 | assert len(decls) == 1 228 | if isinstance(decls[0], six.string_types): 229 | self.append(IdentifierType(node.name, decls[0])) 230 | else: 231 | self.append(decls[0]) 232 | 233 | def visit_FuncDecl(self, node): 234 | decls = self.collect(node) 235 | return_type = decls[-1].type_name 236 | fname = decls[-1].name 237 | args = decls[:-1] 238 | if (len(args) == 1 and isinstance(args[0], IdentifierType) and 239 | args[0].type_name == 'void'): 240 | args = [] 241 | if (self.child_of(c_ast.PtrDecl, -2) and not 242 | self.child_of(c_ast.Typedef, -3)): 243 | # declaring a variable or parameter 244 | name = self.path_name('ft'.format(fname)) 245 | self.decl_stack[0].append(Type(Ptr(Function(return_type, name, args)))) 246 | self.append(name) 247 | else: 248 | self.append(Function(return_type, fname, args)) 249 | 250 | 251 | def visit_PtrDecl(self, node): 252 | decls = self.collect(node) 253 | assert len(decls) == 1 254 | if isinstance(decls[0], six.string_types): 255 | self.append(decls[0]) 256 | else: 257 | self.append(Ptr(decls[0])) 258 | 259 | def visit_ArrayDecl(self, node): 260 | decls = self.collect(node) 261 | assert len(decls) == 1 262 | self.append(Array(decls[0])) 263 | 264 | def visit_Typedef(self, node): 265 | decls = self.collect(node) 266 | if len(decls) != 1: 267 | return 268 | names = str(decls[0]).split() 269 | if names[0] != names[1]: 270 | self.decl_stack[0].append(Type(decls[0])) 271 | 272 | def collect(self, node): 273 | decls = [] 274 | self.decl_stack.append(decls) 275 | name = self.generic_visit(node) 276 | assert self.decl_stack.pop() == decls 277 | return decls 278 | 279 | def path_name(self, tag): 280 | names = [] 281 | for node in self.visit_stack[:-2]: 282 | if hasattr(node, 'declname') and node.declname: 283 | names.append(node.declname) 284 | elif hasattr(node, 'name') and node.name: 285 | names.append(node.name) 286 | return '_{0}_{1}'.format('_'.join(names), tag) 287 | 288 | def child_of(self, type, index=None): 289 | if index is None: 290 | for node in reversed(self.visit_stack): 291 | if isinstance(node, type): 292 | return True 293 | return False 294 | else: 295 | return isinstance(self.visit_stack[index], type) 296 | 297 | def append(self, node): 298 | self.decl_stack[-1].append(node) 299 | 300 | def lines(self): 301 | rv = ['cdef extern from "{0}":'.format(self.hdrname), ''] 302 | for decl in self.decl_stack[0]: 303 | for line in decl.lines(): 304 | rv.append(self.indent + line) 305 | rv.append('') 306 | return rv 307 | 308 | 309 | def preprocess(code, extra_cpp_args=[]): 310 | proc = subprocess.Popen([ 311 | 'cpp', '-nostdinc', '-D__attribute__(x)=', '-I', BUILTIN_HEADERS_DIR, 312 | ] + extra_cpp_args + ['-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 313 | result = [] 314 | result.append(proc.communicate(input=code.encode('utf-8'))[0]) 315 | while proc.poll() is None: 316 | result.append(proc.communicate()[0]) 317 | if proc.returncode: 318 | raise Exception('Invoking C preprocessor failed') 319 | return b''.join(result).decode('utf-8') 320 | 321 | 322 | def parse(code, extra_cpp_args=[], whitelist=None): 323 | preprocessed = preprocess(code, extra_cpp_args=extra_cpp_args) 324 | parser = c_parser.CParser() 325 | ast = parser.parse(preprocessed) 326 | decls = [] 327 | for decl in ast.ext: 328 | if hasattr(decl, 'name') and decl.name not in IGNORE_DECLARATIONS: 329 | if not whitelist or decl.coord.file in whitelist: 330 | decls.append(decl) 331 | ast.ext = decls 332 | return ast 333 | 334 | 335 | def translate(code, hdrname, extra_cpp_args=[], whitelist=None): 336 | """ 337 | to generate pxd mappings for only certain files, populate the whitelist parameter 338 | with the filenames (including relative path): 339 | whitelist = ['/usr/include/baz.h', 'include/tux.h'] 340 | 341 | if the input file is a file that we want in the whitelist, i.e. `whitelist = [hdrname]`, 342 | the following extra step is required: 343 | extra_cpp_args += [hdrname] 344 | """ 345 | extra_incdir = os.path.dirname(hdrname) 346 | extra_cpp_args += ['-I', extra_incdir] 347 | p = AutoPxd(hdrname) 348 | p.visit(parse(code, extra_cpp_args=extra_cpp_args, whitelist=whitelist)) 349 | return str(p) 350 | 351 | 352 | WHITELIST = [] 353 | 354 | @click.command() 355 | @click.argument('infile', type=click.File('rb'), default=sys.stdin) 356 | @click.argument('outfile', type=click.File('wb'), default=sys.stdout) 357 | def cli(infile, outfile): 358 | outfile.write(translate(infile.read(), infile.name)) 359 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import subprocess 3 | 4 | from setuptools import setup 5 | from setuptools.command.develop import develop 6 | from setuptools.command.install import install 7 | from setuptools.command.sdist import sdist 8 | 9 | 10 | def install_libc_headers_and(cmdclass): 11 | def download_fake_libc_include(): 12 | inc = os.path.join('autopxd', 'include') 13 | if os.path.exists(inc): 14 | if not os.path.isdir(inc): 15 | raise Exception( 16 | '"{0}" already exists and is not a directory'.format(inc)) 17 | return 18 | repo = 'https://github.com/eliben/pycparser' 19 | commit = 'a47b919287a33dea55cc02b2f8c5f4be2ee8613c' 20 | url = '{0}/archive/{1}.tar.gz'.format(repo, commit) 21 | subprocess.check_call(( 22 | 'mkdir {0} && cd {0} && ' 23 | 'curl -L -o - {1} | ' 24 | 'tar xfz - --strip-components=3 ' 25 | 'pycparser-{2}/utils/fake_libc_include/' 26 | ).format(inc, url, commit), shell=True) 27 | 28 | class Sub(cmdclass): 29 | def run(self): 30 | download_fake_libc_include() 31 | cmdclass.run(self) 32 | 33 | return Sub 34 | 35 | 36 | VERSION = '1.1.2' 37 | REPO = 'http://github.com/tarruda/python-autopxd' 38 | 39 | 40 | setup( 41 | name='autopxd', 42 | version=VERSION, 43 | description='Automatically generate Cython pxd files from C headers', 44 | packages=['autopxd'], 45 | package_data={'autopxd': ['include/*.h', 'include/**/*.h']}, 46 | author='Thiago de Arruda', 47 | author_email='tpadilha84@gmail.com', 48 | url=REPO, 49 | download_url='{0}/archive/{1}.tar.gz'.format(REPO, VERSION), 50 | license='MIT', 51 | cmdclass={ 52 | 'develop': install_libc_headers_and(develop), 53 | 'install': install_libc_headers_and(install), 54 | 'sdist': install_libc_headers_and(sdist) 55 | }, 56 | install_requires=[ 57 | 'six', 58 | 'Click', 59 | 'pycparser', 60 | ], 61 | entry_points=''' 62 | [console_scripts] 63 | autopxd=autopxd:cli 64 | ''', 65 | ) 66 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import glob 3 | import os.path 4 | import re 5 | import unittest 6 | 7 | import autopxd 8 | 9 | 10 | class AllTests(unittest.TestCase): 11 | pass 12 | 13 | 14 | def gen(test_file): 15 | with open(test_file) as f: 16 | data = f.read() 17 | c, cython = re.split('^-+$', data, maxsplit=1, flags=re.MULTILINE) 18 | c = c.strip() 19 | cython = cython.strip() + '\n' 20 | def test(self): 21 | whitelist = None 22 | cpp_args = [] 23 | if test_file == 'test/whitelist.test': 24 | test_path = os.path.dirname(test_file) 25 | whitelist = ['test/tux_foo.h'] 26 | cpp_args = ['-I', test_path] 27 | actual = autopxd.translate(c, os.path.basename(test_file), cpp_args, whitelist) 28 | self.assertEqual(cython, actual) 29 | return test 30 | 31 | 32 | if __name__ == '__main__': 33 | for file_path in glob.iglob('test/*.test'): 34 | test = gen(file_path) 35 | test_name, _ = os.path.splitext(os.path.basename(file_path)) 36 | setattr(AllTests, 'test_{0}'.format(test_name), test) 37 | unittest.main() 38 | -------------------------------------------------------------------------------- /test/anonymous_enum.test: -------------------------------------------------------------------------------- 1 | enum { 2 | C1 = 5, 3 | C2 = 4, 4 | C3 = 3 5 | }; 6 | 7 | --- 8 | 9 | cdef extern from "anonymous_enum.test": 10 | 11 | cdef enum: 12 | C1 13 | C2 14 | C3 15 | -------------------------------------------------------------------------------- /test/bar_baz.h: -------------------------------------------------------------------------------- 1 | 2 | struct bar; 3 | 4 | void baz(struct bar *, int a); 5 | 6 | struct bar { 7 | int a; 8 | int b; 9 | }; 10 | -------------------------------------------------------------------------------- /test/enum.test: -------------------------------------------------------------------------------- 1 | enum MyEnum { 2 | C1, 3 | C2, 4 | C3 5 | }; 6 | 7 | --- 8 | 9 | cdef extern from "enum.test": 10 | 11 | cdef enum MyEnum: 12 | C1 13 | C2 14 | C3 15 | -------------------------------------------------------------------------------- /test/forward_empty_struct.test: -------------------------------------------------------------------------------- 1 | struct my_struct; 2 | 3 | void my_func(struct my_struct *, int a); 4 | 5 | struct my_struct { 6 | int a; 7 | int b; 8 | }; 9 | 10 | --- 11 | 12 | cdef extern from "forward_empty_struct.test": 13 | 14 | void my_func(my_struct*, int a) 15 | 16 | cdef struct my_struct: 17 | int a 18 | int b 19 | -------------------------------------------------------------------------------- /test/globals.test: -------------------------------------------------------------------------------- 1 | void (*my_func)(int a, char b); 2 | 3 | struct { 4 | int a, b; 5 | } my_anon_struct[10]; 6 | 7 | int c; 8 | 9 | --- 10 | 11 | cdef extern from "globals.test": 12 | 13 | ctypedef void (*_my_func_ft)(int a, char b) 14 | 15 | _my_func_ft my_func 16 | 17 | cdef struct _my_anon_struct_s: 18 | int a 19 | int b 20 | 21 | _my_anon_struct_s my_anon_struct[1] 22 | 23 | int c 24 | -------------------------------------------------------------------------------- /test/inline_proto_nested.test: -------------------------------------------------------------------------------- 1 | void my_func_1(void (*my_cb)(int *a), int b); 2 | 3 | void my_func_2(void (*my_cb2)(void (*my_cb3)(int *a)), int b); 4 | 5 | struct my_struct { 6 | void (*my_func_3)(void (*my_cb1)(int *a), void (*my_cb2)(int *a)); 7 | }; 8 | 9 | --- 10 | 11 | cdef extern from "inline_proto_nested.test": 12 | 13 | ctypedef void (*_my_func_1_my_cb_ft)(int* a) 14 | 15 | void my_func_1(_my_func_1_my_cb_ft my_cb, int b) 16 | 17 | ctypedef void (*_my_func_2_my_cb2_my_cb3_ft)(int* a) 18 | 19 | ctypedef void (*_my_func_2_my_cb2_ft)(_my_func_2_my_cb2_my_cb3_ft my_cb3) 20 | 21 | void my_func_2(_my_func_2_my_cb2_ft my_cb2, int b) 22 | 23 | ctypedef void (*_my_struct_my_func_3_my_cb1_ft)(int* a) 24 | 25 | ctypedef void (*_my_struct_my_func_3_my_cb2_ft)(int* a) 26 | 27 | ctypedef void (*_my_struct_my_func_3_ft)(_my_struct_my_func_3_my_cb1_ft my_cb1, _my_struct_my_func_3_my_cb2_ft my_cb2) 28 | 29 | cdef struct my_struct: 30 | _my_struct_my_func_3_ft my_func_3 31 | -------------------------------------------------------------------------------- /test/inline_proto_struct.test: -------------------------------------------------------------------------------- 1 | struct my_struct { 2 | void (*my_func_1)(void); 3 | void (*my_func_2)(struct my_struct *p); 4 | int (*my_func_3)(char *a1, char **a2, char **a3[3][4]); 5 | int ***(*my_func_4)(char *a1, char **a2, char **a3[3][4]); 6 | }; 7 | 8 | --- 9 | 10 | cdef extern from "inline_proto_struct.test": 11 | 12 | ctypedef void (*_my_struct_my_func_1_ft)() 13 | 14 | ctypedef void (*_my_struct_my_func_2_ft)(my_struct* p) 15 | 16 | ctypedef int (*_my_struct_my_func_3_ft)(char* a1, char** a2, char** a3[1][1]) 17 | 18 | ctypedef int*** (*_my_struct_my_func_4_ft)(char* a1, char** a2, char** a3[1][1]) 19 | 20 | cdef struct my_struct: 21 | _my_struct_my_func_1_ft my_func_1 22 | _my_struct_my_func_2_ft my_func_2 23 | _my_struct_my_func_3_ft my_func_3 24 | _my_struct_my_func_4_ft my_func_4 25 | -------------------------------------------------------------------------------- /test/nested.test: -------------------------------------------------------------------------------- 1 | typedef struct my_s { 2 | union my_nested_u { 3 | char c; 4 | struct my_nested_s { 5 | int i; 6 | } n; 7 | int i; 8 | } n; 9 | unsigned u; 10 | } my_t; 11 | 12 | --- 13 | 14 | cdef extern from "nested.test": 15 | 16 | cdef struct my_nested_s: 17 | int i 18 | 19 | cdef union my_nested_u: 20 | char c 21 | my_nested_s n 22 | int i 23 | 24 | cdef struct my_s: 25 | my_nested_u n 26 | unsigned u 27 | 28 | ctypedef my_s my_t 29 | -------------------------------------------------------------------------------- /test/proto.test: -------------------------------------------------------------------------------- 1 | struct my_struct { 2 | int a, b; 3 | }; 4 | 5 | void my_func_1(void); 6 | void my_func_2(struct my_struct *p); 7 | int my_func_3(char *a1, char **a2, char **a3[3][4]); 8 | int ***my_func_4(char *a1, char **a2, char **a3[3][4]); 9 | void my_func_5(char *, int); 10 | 11 | --- 12 | 13 | cdef extern from "proto.test": 14 | 15 | cdef struct my_struct: 16 | int a 17 | int b 18 | 19 | void my_func_1() 20 | 21 | void my_func_2(my_struct* p) 22 | 23 | int my_func_3(char* a1, char** a2, char** a3[1][1]) 24 | 25 | int*** my_func_4(char* a1, char** a2, char** a3[1][1]) 26 | 27 | void my_func_5(char*, int) 28 | -------------------------------------------------------------------------------- /test/struct.test: -------------------------------------------------------------------------------- 1 | struct some_struct { 2 | int a, *b, **c, ***d; 3 | char ac, *bc, *cc[5]; 4 | }; 5 | 6 | --- 7 | 8 | cdef extern from "struct.test": 9 | 10 | cdef struct some_struct: 11 | int a 12 | int* b 13 | int** c 14 | int*** d 15 | char ac 16 | char* bc 17 | char* cc[1] 18 | -------------------------------------------------------------------------------- /test/tux_foo.h: -------------------------------------------------------------------------------- 1 | #include "bar_baz.h" 2 | 3 | struct tux; 4 | 5 | void foo(struct tux *, int a); 6 | 7 | struct tux { 8 | int a; 9 | int b; 10 | }; 11 | -------------------------------------------------------------------------------- /test/typedef.test: -------------------------------------------------------------------------------- 1 | typedef int custom_int_t; 2 | typedef unsigned long custom_uint_t; 3 | 4 | --- 5 | 6 | cdef extern from "typedef.test": 7 | 8 | ctypedef int custom_int_t 9 | 10 | ctypedef unsigned long custom_uint_t 11 | -------------------------------------------------------------------------------- /test/typedef_anonymous_enum.test: -------------------------------------------------------------------------------- 1 | typedef enum { 2 | C1, 3 | C2, 4 | C3 5 | } MyEnumType; 6 | 7 | --- 8 | 9 | cdef extern from "typedef_anonymous_enum.test": 10 | 11 | cdef enum _MyEnumType_e: 12 | C1 13 | C2 14 | C3 15 | 16 | ctypedef _MyEnumType_e MyEnumType 17 | -------------------------------------------------------------------------------- /test/typedef_anonymous_struct.test: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | int s1, **s2; 3 | char c1, *c2; 4 | } my_struct_t; 5 | 6 | --- 7 | 8 | cdef extern from "typedef_anonymous_struct.test": 9 | 10 | cdef struct _my_struct_t_s: 11 | int s1 12 | int** s2 13 | char c1 14 | char* c2 15 | 16 | ctypedef _my_struct_t_s my_struct_t 17 | -------------------------------------------------------------------------------- /test/typedef_anonymous_union.test: -------------------------------------------------------------------------------- 1 | typedef union { 2 | int s1, **s2; 3 | char c1, *c2; 4 | } my_union_t; 5 | 6 | --- 7 | 8 | cdef extern from "typedef_anonymous_union.test": 9 | 10 | cdef union _my_union_t_u: 11 | int s1 12 | int** s2 13 | char c1 14 | char* c2 15 | 16 | ctypedef _my_union_t_u my_union_t 17 | -------------------------------------------------------------------------------- /test/typedef_enum.test: -------------------------------------------------------------------------------- 1 | typedef enum my_enum { 2 | C1, 3 | C2, 4 | C3 5 | } MyEnumType; 6 | 7 | --- 8 | 9 | cdef extern from "typedef_enum.test": 10 | 11 | cdef enum my_enum: 12 | C1 13 | C2 14 | C3 15 | 16 | ctypedef my_enum MyEnumType 17 | -------------------------------------------------------------------------------- /test/typedef_enum_alt.test: -------------------------------------------------------------------------------- 1 | enum my_enum { 2 | C1, 3 | C2, 4 | C3 5 | }; 6 | 7 | typedef enum my_enum my_enum; 8 | 9 | typedef my_enum MyEnum; 10 | 11 | --- 12 | 13 | cdef extern from "typedef_enum_alt.test": 14 | 15 | cdef enum my_enum: 16 | C1 17 | C2 18 | C3 19 | 20 | ctypedef my_enum MyEnum 21 | -------------------------------------------------------------------------------- /test/typedef_proto.test: -------------------------------------------------------------------------------- 1 | struct my_struct { 2 | int a, b; 3 | }; 4 | 5 | typedef void (*my_func_1)(void); 6 | typedef void (*my_func_2)(struct my_struct *p); 7 | typedef int (*my_func_3)(char *a1, char **a2, char **a3[3][4]); 8 | typedef int ***(*my_func_4)(char *a1, char **a2, char **a3[3][4]); 9 | 10 | --- 11 | 12 | cdef extern from "typedef_proto.test": 13 | 14 | cdef struct my_struct: 15 | int a 16 | int b 17 | 18 | ctypedef void (*my_func_1)() 19 | 20 | ctypedef void (*my_func_2)(my_struct* p) 21 | 22 | ctypedef int (*my_func_3)(char* a1, char** a2, char** a3[1][1]) 23 | 24 | ctypedef int*** (*my_func_4)(char* a1, char** a2, char** a3[1][1]) 25 | -------------------------------------------------------------------------------- /test/typedef_struct.test: -------------------------------------------------------------------------------- 1 | typedef struct my_struct_s { 2 | int s1, **s2; 3 | char c1, *c2; 4 | } my_struct_t; 5 | 6 | --- 7 | 8 | cdef extern from "typedef_struct.test": 9 | 10 | cdef struct my_struct_s: 11 | int s1 12 | int** s2 13 | char c1 14 | char* c2 15 | 16 | ctypedef my_struct_s my_struct_t 17 | -------------------------------------------------------------------------------- /test/typedef_union.test: -------------------------------------------------------------------------------- 1 | typedef union my_union_u { 2 | int s1, **s2; 3 | char c1, *c2; 4 | } my_union_t; 5 | 6 | --- 7 | 8 | cdef extern from "typedef_union.test": 9 | 10 | cdef union my_union_u: 11 | int s1 12 | int** s2 13 | char c1 14 | char* c2 15 | 16 | ctypedef my_union_u my_union_t 17 | -------------------------------------------------------------------------------- /test/union.test: -------------------------------------------------------------------------------- 1 | union some_union { 2 | int a, *b, **c, ***d; 3 | char ac, *bc, *cc[5]; 4 | }; 5 | 6 | --- 7 | 8 | cdef extern from "union.test": 9 | 10 | cdef union some_union: 11 | int a 12 | int* b 13 | int** c 14 | int*** d 15 | char ac 16 | char* bc 17 | char* cc[1] 18 | -------------------------------------------------------------------------------- /test/whitelist.test: -------------------------------------------------------------------------------- 1 | #include "tux_foo.h" 2 | 3 | --- 4 | 5 | cdef extern from "whitelist.test": 6 | 7 | void foo(tux*, int a) 8 | 9 | cdef struct tux: 10 | int a 11 | int b --------------------------------------------------------------------------------