Exemplo n.º 1
0
def make_cppclass(scope, cl_name, decl):
    import _cppyy

    # get a list of base classes for class creation
    bases = [get_pycppclass(base) for base in decl.get_base_names()]
    if not bases:
        bases = [CPPClass,]
    else:
        # it's possible that the required class now has been built if one of
        # the base classes uses it in e.g. a function interface
        try:
            return scope.__dict__[cl_name]
        except KeyError:
            pass

    # prepare dictionary for metaclass
    d_meta = {}

    # prepare dictionary for python-side C++ class representation
    def dispatch(self, m_name, signature):
        cppol = decl.__dispatch__(m_name, signature)
        return MethodType(cppol, self, type(self))
    d_class = {"__cppdecl__"   : decl,
         "__new__"      : make_new(decl),
         "__module__"   : make_module_name(scope),
         "__cppname__"  : decl.__cppname__,
         "__dispatch__" : dispatch,
         }

    # insert (static) methods into the class dictionary
    for m_name in decl.get_method_names():
        cppol = decl.get_overload(m_name)
        d_class[m_name] = cppol

    # add all data members to the dictionary of the class to be created, and
    # static ones also to the metaclass (needed for property setters)
    for d_name in decl.get_datamember_names():
        cppdm = decl.get_datamember(d_name)
        d_class[d_name] = cppdm
        if _cppyy._is_static_data(cppdm):
            d_meta[d_name] = cppdm

    # create a metaclass to allow properties (for static data write access)
    metabases = [type(base) for base in bases]
    cl_meta = type(CPPClassMeta)(cl_name+'_meta', _drop_cycles(metabases), d_meta)

    # create the python-side C++ class
    pycls = cl_meta(cl_name, _drop_cycles(bases), d_class)

    # store the class on its outer scope
    setattr(scope, cl_name, pycls)

    # the call to register will add back-end specific pythonizations and thus
    # needs to run first, so that the generic pythonizations can use them
    import _cppyy
    _cppyy._register_class(pycls)
    _pythonize(pycls, pycls.__cppname__)
    return pycls
Exemplo n.º 2
0
def get_scoped_pycppitem(scope, name, type_only=False):
    import _cppyy

    # resolve typedefs/aliases: these may cross namespaces, in which case
    # the lookup must trigger the creation of all necessary scopes
    scoped_name = (scope == gbl) and name or (scope.__cppname__ + '::' + name)
    final_scoped_name = _cppyy._resolve_name(scoped_name)
    if final_scoped_name != scoped_name:
        pycppitem = get_pycppitem(final_scoped_name)
        # also store on the requested scope (effectively a typedef or pointer copy)
        setattr(scope, name, pycppitem)
        return pycppitem

    pycppitem = None

    # scopes (classes and namespaces)
    cppitem = _cppyy._scope_byname(final_scoped_name)
    if cppitem:
        if cppitem.is_namespace():
            pycppitem = make_cppnamespace(scope, name, cppitem)
        else:
            pycppitem = make_cppclass(scope, name, cppitem)

    if type_only:
        return pycppitem

    # templates
    if not cppitem:
        cppitem = _cppyy._is_template(final_scoped_name)
        if cppitem:
            pycppitem = make_cpptemplatetype(scope, name)
            setattr(scope, name, pycppitem)

    # functions
    if not cppitem:
        try:
            cppitem = scope.__cppdecl__.get_overload(name)
            setattr(scope.__class__, name, cppitem)
            pycppitem = getattr(scope, name)  # binds function as needed
        except AttributeError:
            pass

    # data
    if not cppitem:
        try:
            cppdm = scope.__cppdecl__.get_datamember(name)
            setattr(scope, name, cppdm)
            if _cppyy._is_static_data(cppdm):
                setattr(scope.__class__, name, cppdm)
            pycppitem = getattr(scope, name)  # gets actual property value
        except AttributeError:
            pass

    if pycppitem is not None:  # pycppitem could be a bound C++ NULL, so check explicitly for Py_None
        return pycppitem

    raise AttributeError("'%s' has no attribute '%s'" % (str(scope), name))