コード例 #1
0
def main():
    #fn = sys.argv[1]
    fn = settings.files[0]

    app = creator_app()

    app.process_include_files()

    classes = {}

    temp_cpp_ss = []
    temp_cpp_ss.append('#define SWIG')
    temp_cpp_ss.append('#define CREATE_VCW')

    for s in settings.defines:
        temp_cpp_ss.append('#define %s'%s)

    for s in app.c_define_lines:
        temp_cpp_ss.append(s)

    for fn in settings.files:
        # Create private copies with culled headers
        #tfn = parse_cpp_header.get_temp_filename('h')
        temp_cpp_ss.append(app.load_file(fn))
        #temp_cpp_ss.append('#include <%s>'%fn)

    temp_cpp_ss.append('')

    temp_cpp = '\n'.join(temp_cpp_ss)
    temp_cpp = temp_cpp.replace('#include','//#include')

    classes = cpp_header_parser.parse_header(temp_cpp, settings.include_paths, {})
    if classes is None:
        return

    # Distribute and check class configs
    for cls in classes.itervalues():
        cls_config = settings.class_config.get(cls.name, {})
        cls.cls_config = cls_config

        for k in cls_config.keys():
            if not k in ALLOWED_CLS_CONFIG_KEYS:
                raise AssertionError("'%s' is not supported class_config key"%k)

    # Update derived classes configs
    for cls in classes.itervalues():
        derived_classes = cls.find_derived_classes(classes)
        for ocls in derived_classes:
            if not ocls.cls_config:
                ocls.cls_config = cls.cls_config

    # Add 'pyvirtual' flag to functions for which we should create wrapper
    for cls in classes.itervalues():
        cls_config = cls.cls_config
        for func in cls.func_list:
            if 'virtual' in func.flags:

                excluded = False
                for fn in cls_config.get('excluded_methods', []):
                    if func.name == fn:
                        excluded = True
                        break

                if not excluded:
                    func.flags.add('pyvirtual')

        # Also add new member, - a list of virtual
        # functions that are added (exclusively) in
        # add_wrapper_code-section below
        cls.additional_virtual_functions = []

    #
    # Parse 'add_wrapper_code' section
    add_wrapper_code = getattr(settings, 'add_wrapper_code', None)
    add_wrapper_code_classes = {}
    if add_wrapper_code:
        add_wrapper_code_classes = cpp_header_parser.parse_header(add_wrapper_code, settings.include_paths, {})
        if add_wrapper_code_classes is None:
            return

        #
        # Add function with 'pyvirtual' flag to main classes dictionary straight away
        for class_name, awc_cls in add_wrapper_code_classes.iteritems():
            try:
                cls = classes[class_name]
            except KeyError:
                raise AssertionError("Classes declared in add_wrapper_code "
                                     "section must exist in included header "
                                     "files. Class '%s' did not exist." % \
                                     (class_name))

            derived_classes = cls.find_derived_classes(classes)

            for func in awc_cls.func_list:
                if 'pyvirtual' in func.flags:
                    # Must create wrapper for this
                    cls.additional_virtual_functions.append(func)
                    for dcls in derived_classes:
                        dcls.additional_virtual_functions.append(func)

    v_py_funcnames = set()
    class_codes = []
    funcsigmap = {}

    dbg_func = 'MySWIGOutputDebugString'

    # Add this string to func names when stored into object
    func_appendum = '_t_'
    pfunc_addendum = '_Parent'
    #if settings.logging:
    #else:

    swig_ignores = app.swig_ignores

    for class_name, cls in classes.iteritems():

        cls_config = cls.cls_config
        script_object_member = cls_config.get('script_object_member',
                                              settings.default_script_object_member)

        #print class_name
        #print cls.super_classes

        base_cb_class = None
        fscls = class_name

        while fscls:
            fscls = classes[fscls].find_super_class(classes, settings.classes)
            if fscls:
                base_cb_class = fscls

        if ((not class_name in settings.classes and not base_cb_class) or
             class_name in swig_ignores):
            continue

        class_name_orig = class_name

        py_class_name = None

        for fs,ss in settings.class_renamers:

            re_fs = re.compile(fs)
            if re_fs.match(class_name):
                py_class_name = re_fs.sub(ss, class_name)
                break

        if not py_class_name:
            py_class_name = 'Py%s'%class_name

        print "Creating callback class for '%s' ('%s')"%(class_name,py_class_name)

        hstatics = []
        hdecls = []
        hdecls2 = []
        sstatics = []
        simps = []
        plain_functions = []
        sstaticsets = []
        constructors = []
        cdecls = []
        cimps = []

        #
        # Look for additional functions to implement (from add_wrapper_code-section)
        plain_functions_to_add = []

        for awc_class_name, awc_cls in add_wrapper_code_classes.iteritems():
            if class_name == awc_class_name or cls.find_super_class(classes, [awc_class_name]):
                for func in awc_cls.func_list:
                    if not ('pyvirtual' in func.flags):
                        plain_functions_to_add.append(func)

        for func in plain_functions_to_add:
            fpp = func.decl.find(func.name)-1
            rest_of_decl = func.decl[fpp+1:]

            hdecls.append('    %s'%func.construct_decl())
            plain_functions.append(func)

        plain_function_names = set([func.name for func in plain_functions_to_add])

        # Add functions from parent callback classes
        use_func_list = cls.get_all_functions(classes)
        existing_func_names = set([func.name for func in use_func_list])
        use_func_list.extend(cls.additional_virtual_functions)
        use_func_list.sort(lambda x,y: cmp(x.name, y.name))

        template_vars = {'py_class_name':py_class_name, 'class_name':class_name_orig,
                         'script_object_member':script_object_member}

        for func in use_func_list:

            func_name = func.name

            #if class_name == 'wxPGTextCtrlAndButtonEditor':
            #    print '%s  flags: %s  in_this: %s'%(func_name,repr(func.flags),(func_name in cls.func_names))

            fpp = func.decl.find(func_name)-1
            rest_of_decl = func.decl[fpp+1:]
            ppp = func.decl.find('(')
            args_of_decl = func.decl[ppp:]
            arguments = func.arguments
            args_str_nodefs = ', '.join(['%s %s'%(a[0],a[1]) for a in arguments])
            arg_names_list = ', '.join([a[1] for a in arguments])
            func_post_decl = ''
            if 'const' in func.flags:
                func_post_decl = ' const'

            func_decl_impl = '%s(%s)%s'%(func_name, args_str_nodefs, func_post_decl)

            if arguments:
                args_str_nodefs_cont = ', '+args_str_nodefs
            else:
                args_str_nodefs_cont = ''

            #
            # Constructor
            if func_name == class_name:
                cdecls.append('    %s%s;'%(py_class_name,args_of_decl))
                ss = []
                ss.append('\n%s::%s(%s)'%(py_class_name,py_class_name,args_str_nodefs))
                ss.append('    : %s(%s)'%(class_name,arg_names_list))
                ss.append('{')
                if settings.logging:
                    ss.append('    %s(wxT("%s::%s()"));\n'%(dbg_func,py_class_name,py_class_name))
                ss.append('    Init();')
                ss.append('}')
                cimps.append('\n'.join(ss))
                continue

            # Don't add non-virtual methods or destructors
            if func_name[0] == '~' or not 'pyvirtual' in func.flags:
                continue

            if func_name in plain_function_names:
                raise AssertionError("%s::%s() defined in add_wrapper_code-section conflicted " \
                                     "with virtual function with same name"%(class_name, func_name))

            if not class_name in app.callback_classes:
                app.add_callback_class(class_name, py_class_name, script_object_member)

            # Determine name with which this functions is exposed in Python
            py_func_name = func_name
            if func_name.startswith('Py') and func_name[2].isupper():
                py_func_name = func_name[2:]
            v_py_funcnames.add(py_func_name)

            # Add dummy names instead of empty names, where needed.
            for i in range(0,len(arguments)):
                a = arguments[i]
                if not a[1]:
                    print 'ERROR: You must specify names for all arguments for %s::%s'%(class_name,func.name)
                    #arguments[i] = (a[0],'_arg%i'%i)
                    return

            if func.retval == 'void':
                rets_void = True
                retvals_count = 0
                default_return = 'return;'
                ret_with_func = ''
            else:
                rets_void = False
                retvals_count = 1
                default_return = 'return %s;'%(cpp_header_parser.get_default_value_for_type(func.retval))
                ret_with_func = 'return '

            if not 'pure' in func.flags:
                add_pfunc = True
            else:
                add_pfunc = False

            decl_s = '    virtual %s;'%(func.decl)

            # If it was pure, we need to add it to interface as well, so that SWIG knows the
            # class is, infact non-abstract now.
            if 'pure' in func.flags:
                hdecls2.append(decl_s)

            hdecls.append(decl_s)

            pfimp = ''
            """
            add_pfunc = False
            if add_pfunc:
                s = '    %s %s%s%s;'%(func.retval,func.name,pfunc_addendum,args_of_decl)
                hdecls.append(s)
                hdecls2.append(s)

                ss = []
                ss.append('')
                ss.append('%s %s::%s%s(%s)%s { %s%s::%s(%s); }'%(func.retval,py_class_name,func.name,pfunc_addendum,args_str_nodefs,func_post_decl,ret_with_func,class_name,func.name,arg_names_list))
                pfimp = '\n'.join(ss)
            else:
                pfimp = ''
            """

            #
            # Generate wrapper function implementation code

            #
            # Generate implementation
            #
            si = []
            si.append('')
            si.append('%s %s::%s'%(func.retval,py_class_name,func_decl_impl))
            si.append('{')
            si.append('    wxPyBlock_t blocked = wxPyBeginBlockThreads();')
            if settings.logging:
                si.append('    %s(wxT("%s::%s() entry"));'%(dbg_func,py_class_name,func.name))
            si.append('')

            #
            # Fall-back check
            si.append('    PyObject* cls_ = PyObject_GetAttr((PyObject*)%s, gs___class___Name);'%(script_object_member))

            si.append('    PyObject* funcobj = NULL;')
            si.append('    if ( PyObject_HasAttr(cls_, gs_%s_Name) == 1 ) funcobj = PyObject_GetAttr(cls_, gs_%s_Name);'%(py_func_name, py_func_name))
            si.append('    Py_DECREF(cls_);')
            si.append('    if ( !funcobj || PyObject_HasAttr((PyObject*)%s, gs__super_call_Name) == 1 )'%(script_object_member))
            #si.append('    if ( PyObject_HasAttr(cls_, gs_%s_Name) != 1 || PyObject_HasAttr(m_scriptObject, gs__super_call_Name) == 1 )'%(py_func_name))
            si.append('    {')
            si.append('        wxPyEndBlockThreads(blocked);')

            if not 'pure' in func.flags:
                if settings.logging:
                    si.append('        %s(wxT("%s::%s() exit (fall-back)"));'%(dbg_func,py_class_name,func.name))

                # If class implemented base version, return it
                if func_name in existing_func_names:
                    if not rets_void:
                        si.append('        return %s::%s(%s);'%(class_name,func.name,arg_names_list))
                    else:
                        si.append('        %s::%s(%s);'%(class_name,func.name,arg_names_list))
                        si.append('        return;')
                else:
                    # Apply code from version in add_wrapper_code
                    # (available as func.content)
                    base_func_content = func.content
                    if not base_func_content:
                        raise AssertionError('%s::%s() should have function content'%(class_name, func_name))
                    si.append(cpp_header_parser.indent(base_func_content%template_vars, 8))
            else:
                if settings.logging:
                    si.append('        %s(wxT("%s::%s() exit (not implemented!!!)"));'%(dbg_func,py_class_name,func.name))
                si.append('        PyErr_SetString(PyExc_TypeError,"this method must be implemented");')
                si.append('        %s'%default_return)

            si.append('    }')
            #si.append('    PyObject* funcobj = PyObject_GetAttr(cls_, gs_%s_Name);'%(py_func_name))
            #if settings.logging: si.append('    %s("6");'%dbg_func)

            pre_func = '\n'.join(si)

            si = []

            # Prepare arguments
            prepss, unprepss, retvalprepss, signature = app.get_swig_typeconv_out(arguments, is_callback = True)
            argin_typemaps = len([a_ for a_ in retvalprepss if a_])
            retvals_count += argin_typemaps

            if retvals_count > 1:
                pyrvn = 'tpl'
            else:
                pyrvn = 'res'

            si.append('    PyObject* %s;'%pyrvn)

            # Map new argument list according to callback typemaps used
            used_args = []
            for i in range(0,len(arguments)):
                if prepss[i]:
                    used_args.append(arguments[i])

            # Form typemap-based function signature
            signature = func.retval + signature

            simps.append((signature,pre_func,func,rets_void,pfimp))

            # Don't redo this method, if common parts for function with this signature was already done
            if signature in funcsigmap:
                funcsigmap[signature][3] += 1
                continue

            i = 0
            for arg_type,arg_name in arguments:
                ps = prepss[i]
                if ps:
                    si.append('    PyObject* py_%s;'%arg_name)
                    si.append('%s'%ps)
                i += 1
                #si.append('%s'%app.get_swig_typeconv_out(arg_type, arg_name,'py_%s'%arg_name))

            # Python method call
            #si.append('\n    PyObject* %s = PyObject_CallMethodObjArgs(self, funcname,'%(pyrvn))

            if used_args:
                s_ = ''.join(['py_%s, '%(a[1]) for a in used_args])
            else:
                s_ = ''

            si.append('    %s = PyObject_CallFunctionObjArgs(funcobj, self, %sNULL);'%(pyrvn,s_))

            """
            for arg_type,arg_name in used_args:
                si.append('                                               py_%s,'%arg_name)

            si.append('                                               NULL);\n')
            """
            si.append('    Py_DECREF(funcobj);')

            # Unprepare arguments
            unprepss.reverse()
            lines_added = 0
            for ps in unprepss:
                if ps:
                    si.append('%s'%ps)
                    lines_added += 1

            #if lines_added:
            #    si.append('')

            si.append('    if (PyErr_Occurred()) SWIG_fail;')
            si.append('    {')

            #
            # Return value conversion
            if not rets_void:
                in_prepss, in_unprepss, in_retvalprepss = app.get_swig_typeconv_in([(func.retval,'retval')], is_callback = True)
                si.append('    %s retval;'%func.retval)

            # If argin values were met, we need to prepare to process a sequence
            if retvals_count > 1:
                si.append('    long tpl_count = -1;')
                si.append('    if ( PySequence_Check(tpl) ) {')
                si.append('        PyObject* py_tpl_count = PyInt_FromLong((long)0);')
                si.append('        PySequence_Count(tpl, py_tpl_count);')
                si.append('        tpl_count = PyInt_AsLong(py_tpl_count);')
                si.append('        Py_DECREF(py_tpl_count);')
                si.append('    }')
                si.append('    if ( tpl_count != %i ) {'%retvals_count)
                si.append('        Py_DECREF(tpl);')
                si.append('        PyErr_SetString(PyExc_TypeError, "Expected tuple of %i items as a return value.");'%retvals_count)
                si.append('        SWIG_fail;')
                si.append('    }')
                si.append('')
                si.append('    PyObject* res;')

                ret_handlers = []

                if not rets_void:
                    ret_handlers.append(in_prepss[0])

                ret_handlers.extend(retvalprepss)

                i = 0
                for ps in ret_handlers:
                    if ps:
                        si.append('    res = PySequence_GetItem(%s, %i);'%(pyrvn,i))
                        si.append(ps)
                        si.append('')
                        i += 1

                si.append('    Py_DECREF(tpl);')

            elif retvals_count == 1:
                si.append(in_prepss[0])
            else:
                # DecRef the None-result
                si.append('    Py_DECREF(res);')

            # Check if we need to add fail-label
            need_fail = True
            #need_fail = False
            #for s in si:
            #    if s.find('goto fail') >= 0 or s.find('SWIG_fail') >= 0 or s.find('SWIG_exception_fail') >= 0:
            #        need_fail = True
            #        break

            # Finalize
            if not rets_void:
                si.append('    wxPyEndBlockThreads(blocked);')
                si.append('    return retval;')
                si.append('    }')
                if need_fail:
                    si.append('  fail:')
                    si.append('    if ( PyErr_Occurred() ) PyErr_Print();')
                    si.append('    wxPyEndBlockThreads(blocked);')
                    si.append('    %s'%default_return);
            else:
                si.append('    }')
                if need_fail:
                    si.append('  fail:')
                    si.append('    wxPyEndBlockThreads(blocked);')

            sig_num = len(funcsigmap)
            """rod2 = rest_of_decl[rest_of_decl.find('(')+1:]
            if rod2.find(')') > 0:
                rod2 = (', '+rod2).replace('  ',' ')
            if rod2.endswith('const'):
                rod2 = rod2[:-5]"""
            #common_func_start = '%s _CommonCallback%i(wxPyBlock_t blocked, PyObject* self, PyObject* funcname%s)'%(func.retval,sig_num,args_str_nodefs_cont)
            common_func_start = '%s _CommonCallback%i(wxPyBlock_t blocked, PyObject* self, PyObject* funcobj%s)'%(func.retval,sig_num,args_str_nodefs_cont)

            funcsigmap[signature] = [sig_num,common_func_start,'\n'.join(si),1]

        if not cdecls:
            cdecls.append('    %s();'%py_class_name)
            ss = []
            ss.append('\n%s::%s()'%(py_class_name,py_class_name))
            ss.append('    : %s()'%(class_name))
            ss.append('{')
            if settings.logging:
                ss.append('    %s(wxT("%s::%s()"));'%(dbg_func,py_class_name,py_class_name))
            ss.append('    Init();')
            ss.append('}')
            cimps.append('\n'.join(ss))

        if settings.logging:
            dtor_log = '\n    %s(wxT("%s::~%s()"));'%(dbg_func,py_class_name,py_class_name)
        else:
            dtor_log = ''

        template_vars.update({'func_decls':'\n'.join(hdecls),'ctor_decls':'\n'.join(cdecls),
                         'ctor_imps':'\n'.join(cimps), 'dtor_log':dtor_log})


        # Interface-class code
        scl = app.scl
        scl.append('')
        scl.append('class %s : public %s'%(py_class_name,class_name))
        scl.append('{')
        scl.append('public:')

        if '__init__append' in cls_config:
            init_append_s = '; %s' % cls_config['__init__append']
        else:
            init_append_s = ''

        scl.append('    %%pythonAppend %s "self._SetSelf(self); self._RegisterMethods()%s"' %
                    (py_class_name, init_append_s))
        scl.append(template_vars['ctor_decls'])
        scl.append('%pythoncode {')
        scl.append('    def CallSuperMethod(self, *args, **kwargs):')
        scl.append('        funcname = args[0]')
        scl.append('        args2 = list(args)')
        scl.append('        args2[0] = self')
        scl.append('        self._super_call = True')
        scl.append('        try:')
        scl.append('            res = getattr(%s, funcname)(*args2, **kwargs)'%py_class_name)
        scl.append('        finally:')
        scl.append('            del self._super_call')
        scl.append('        return res')
        scl.append('')
        scl.append('    def _RegisterMethods(self):')
        scl.append('        cls = self.__class__')
        scl.append('        if not hasattr(cls,\'_pyswig_methods_registered\'):')
        scl.append('            cls._pyswig_methods_registered = True')
        scl.append('            ls = [ab for ab in cls.__dict__.iteritems()]')
        scl.append('            for a, b in ls:')
        scl.append('                if not a.startswith(\'_\'):')
        scl.append('                    setattr(cls, \'%%s%s\'%%a, b)'%func_appendum)
        scl.append('}')
        scl.append('    void _SetSelf(PyObject *self);')
        for s_ in hdecls2:
            scl.append(s_)
        # Add code that copies function-objects to self
        scl.append('};')

        class_code = """\

class %(py_class_name)s : public %(class_name)s {
public:
    %(ctor_decls)s
    virtual ~%(py_class_name)s();
    void _SetSelf(PyObject *self);
%(func_decls)s
private:
    void Init() { if ( !gs_funcNamesInitialized ) _InitFuncNames(); }
};

static PyObject* gs_%(py_class_name)s_pyClass = NULL;

%(ctor_imps)s

%(py_class_name)s::~%(py_class_name)s()
{%(dtor_log)s
    if (%(script_object_member)s) { _deleteOwningObject(%(script_object_member)s); %(script_object_member)s = NULL; }
}

void %(py_class_name)s::_SetSelf(PyObject *self)
{
    if ( !gs_%(py_class_name)s_pyClass )
    {
        gs_%(py_class_name)s_pyClass = PyObject_GetAttr(self, gs___class___Name);
        Py_DECREF(gs_%(py_class_name)s_pyClass);
    }
    if ( !%(script_object_member)s ) {
        %(script_object_member)s = self;
        Py_INCREF(self);
    }
}
"""%template_vars

        class_codes.append((class_code, py_class_name, script_object_member, simps, plain_functions, template_vars))


    ss = ['// THIS FILE HAS BEEN AUTO-GENERATED BY %s' % \
          (SCRIPT_NAME.upper())]

    #
    # Add some helper functions
    s = '''\

#ifndef SWIG_IsOK
    #define SWIG_IsOK(r)               (r >= 0)
#endif

#ifndef Py_RETURN_NONE
    #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
#endif

void _deleteOwningObject(void* obj)
{
    // Crashes sometimes (on app exit, it seems), so we need to disable it
    /*if ( Py_IsInitialized() )
    {
        wxPyBlock_t blocked = wxPyBeginBlockThreads();
        Py_XDECREF((PyObject*)obj);
        wxPyEndBlockThreads(blocked);
    }*/
}
    '''
    ss.append(s)

    #
    # Add code to manage static python string representations of function names
    v_py_funcnames = list(v_py_funcnames)
    v_py_funcnames.sort()
    #ss.append('#include <Streams.h>')
    ss.append('')

    ss.append('static bool gs_funcNamesInitialized = false;')
    ss.append('static PyObject* gs___class___Name = NULL;')
    ss.append('static PyObject* gs___dict___Name = NULL;')
    ss.append('static PyObject* gs__super_call_Name = NULL;')

    # Declarations
    for s in v_py_funcnames:
        ss.append('static PyObject* gs_%s_Name = NULL;'%s)

    ss.append('')
    ss.append('static void _InitFuncNames()')
    ss.append('{')
    ss.append('    gs___dict___Name = PyString_FromString("__dict__");')
    ss.append('    gs___class___Name = PyString_FromString("__class__");')
    ss.append('    gs__super_call_Name = PyString_FromString("_super_call");')

    for s in v_py_funcnames:
        ss.append('    gs_%s_Name = PyString_FromString("%s%s");'%(s,s,func_appendum))
    ss.append('    gs_funcNamesInitialized = true;')
    ss.append('}')
    ss.append('')

    # Generate shared callback function implementations
    for signature,tpl in funcsigmap.iteritems():
        sig_num, common_func_start, func_imp, sig_count = tpl
        if sig_count > 1:
            # Shared implementation
            ss.append('')
            ss.append('%s'%common_func_start)
            ss.append('{')
            ss.append(func_imp)
            ss.append('}')

    # Generate callback class code
    for s, py_class_name, script_object_member, simps, plain_functions, template_vars in class_codes:
        ss.append(s)

        for func in plain_functions:
            ss.append(func.construct_impl_head(class_name=py_class_name))
            ss.append(func.content%template_vars)
            ss.append('')

        for signature, pre_func, func, rets_void, pfimp in simps:
            sig_num, common_func_start, func_imp, sig_count = funcsigmap[signature]

            ss.append(pre_func)

            if sig_count > 1:
                # Shared implementation
                if not rets_void:
                    ret_with_func = 'return '
                else:
                    ret_with_func = ''

                #cc_call_pre = '_CommonCallback%i(blocked, m_scriptObject, gs_%s_Name'%(sig_num,func.name)
                cc_call_pre = '%s_CommonCallback%i(blocked, (PyObject*)%s, funcobj'%(ret_with_func,sig_num, script_object_member)

                if len(func.arguments) > 0:
                    ss.append('    %s, %s);'%(cc_call_pre,', '.join([a[1] for a in func.arguments])))
                else:
                    ss.append('    %s);'%cc_call_pre)
            else:
                # Private implementation
                ss.append(func_imp.replace('self','((PyObject*)%s)'%script_object_member).replace('funcname','gs_%s_Name'%func.name))

            if settings.logging:
                ss.append('    %s(wxT("%s::%s() exit"));'%(dbg_func,py_class_name,func.name))
            ss.append('}')
            ss.append(pfimp)


    # Wrap it inside "SWIG-C-code-indicators", so the code can be included
    # when running SWIG projname.i.
    s = '%%{\n\n%s\n\n%%}\n'%('\n'.join(ss))

    f = file(os.path.join(settings.output_dir,'%s_cbacks.cpp'%settings.projname),'wt')
    f.write(s)
    f.close()

    s = '\n'.join(app.scl)

    f = file(os.path.join(settings.output_dir,'%s_cbacks.i'%settings.projname),'wt')
    f.write(s)
    f.close()

    out_typemaps = app.typemaps['in'].keys()
    out_typemaps.sort()
コード例 #2
0
    def process_include_files(self):
        from cpp_header_parser import split_argument_list, indent
        from cpp_header_parser import find_balanced_parenthesis

        re_typemap = re.compile('%typemap\s*\(\s*([^()]+)\s*\)([^{]+){',re.I)

        for fn in settings.includes:

            print("Loading include '%s'" % fn)

            s = self.load_file(fn)

            if s:
                s = cpp_header_parser.purge_comments(s)

                # Find C++ defines
                for m in re_cdefine.finditer(s):
                #{
                    c_define = m.group(0).strip()
                    if c_define[-1] == '\\':
                    #{
                        raise NotImplementedError('Multi-line defines not '
                                                  'yet supported')
                    #}
                    self.c_define_lines.append(c_define)
                #}

                # Find SWIG ignore directives
                for m in re_swig_ignore.finditer(s):
                #{
                    self.swig_ignores.add(m.group(1).strip())
                #}

                s = cpp_header_parser.process_and_run_macros(s,
                    settings.include_paths,
                    is_swig=True)

                # Load typemaps
                pos = 0
                while 1:
                    m = re_typemap.search(s, pos)
                    if not m:
                        break

                    # Get type options
                    tts = [s_.strip() for s_ in m.group(1).split(',')]
                    tm_type = tts[0]
                    tm_options = tts[1:]

                    tm_sdatatype = m.group(2)

                    parens_pos = tm_sdatatype.find('(')
                    if parens_pos >= 0:
                        # There is either multiple datatypes, or temp arg list.
                        pre_p = tm_sdatatype[:parens_pos].strip()
                        if len(pre_p) > 0:
                            # Temp arg list
                            tm_datatypes = split_argument_list(pre_p)
                            tm_tempdata,i_ = split_argument_list(tm_sdatatype,
                                parens_pos, def_vals = True)
                        else:
                            # Multiple args
                            tm_datatypes,i_ = split_argument_list(tm_sdatatype,
                                parens_pos)
                            tm_tempdata = []
                    else:
                        tm_datatypes = split_argument_list(tm_sdatatype)
                        tm_tempdata = []

                    tm_start = m.end()-1

                    tm_end = find_balanced_parenthesis(s, tm_start, '{', '}')

                    tm_content = indent(s[tm_start+1:tm_end-1],4).rstrip()

                    #print tm_type, tm_datatypes
                    #print tm_options
                    #print tm_tempdata
                    #print tm_content

                    #
                    # FIXME: This is a temporary fix - override all wxVariant
                    #        typemaps with those found in our own files.
                    ignore_this = False
                    if fn == 'my_typemaps.i':
                        for ig_typemap in settings.ignore_typemaps_from_base:
                            for tn, vn in tm_datatypes:
                                if tn.startswith(ig_typemap):
                                    print('IGNORED %s typemap from %s' % \
                                          (tm_datatypes, fn))
                                    ignore_this = True
                                    break
                            if ignore_this:
                                break

                    # Do not store options, they are usually just
                    # useless precedence=SWIG_TYPECHECK_POINTER for typecheck.
                    if not ignore_this:
                        self.add_typemap(tm_type, tm_datatypes, tm_tempdata,
                                         tm_content)

                    pos = m.end()