staticmethod and namespaces

darnzen darnzen at gmail.com
Fri Feb 26 10:57:38 EST 2010


On Feb 26, 9:41 am, "Diez B. Roggisch" <de... at nospam.web.de> wrote:
> Am 26.02.10 16:32, schrieb darnzen:
>
>
>
>
>
> > On Feb 26, 3:15 am, "Diez B. Roggisch"<de... at nospam.web.de>  wrote:
> >> Am 26.02.10 06:07, schrieb darnzen:
>
> >>> Having an odd problem that I solved, but wondering if its the best
> >>> solution (seems like a bit of a hack).
>
> >>> First off, I'm using an external DLL that requires static callbacks,
> >>> but because of this, I'm losing instance info. It could be import
> >>> related? It will make more sense after I diagram it:
>
> >>> #Module main.py
> >>> from A import *
>
> >>> class App:
> >>>       def sperg(self):
> >>>            self.a = A()
>
> >>> app = App()
> >>> [main loop and such]
> >>>    -----------------------------
> >>> # Module A.py
> >>> import main
> >>> class Foo:
> >>>         Selves=[]
> >>>        def __init__(self):
> >>>                  Foo.Selves.append(self)
> >>>        @staticmethod
> >>>        def chum_callback(nType, nP):
> >>>                  # Need to access function / data in app instance
> >>>                  app.sperg(nP)
> >>>                  # Need to access func data in Foo
> >>>                  # I'm pulling 'self' ouf of list made in constructor
> >>>                  self = Foo.getSelf(nP)
>
> >>>        def getSelf(nP):
> >>>                  return self.Selves[nP]
>
> >>> ---------------------------------------------------------------------
> >>> So basically I added a list of instances to the base class so I can
> >>> get at them from the staticmethod.
> >>> What's bothering me the most is I can't use the global app instance in
> >>> the A.py module.
>
> >>> How can I get at the app instance (currently I'm storing that along
> >>> with the class instance in the constructor)?
> >>> Is there another way to do this that's not such a hack?
>
> >>> Sorry for the double / partial post :(
>
> >> Can you show how you pass the staticmethod to the C-function? Is the DLL
> >> utilized by ctypes?
>
> >> I don't see any reason you couldn't use a bound method, which would give
> >> you your self, instead relying on global state.
>
> >> Diez
>
> > __main__.K<<  *facepalm* should of tried that!
>
> > Yeah I'm using ctypes. The DLL callback set ups are as follows. The
> > local callback is in the App namespace (in this case, some callbacks
> > are in different modules as noted in OP), but still no access to self:
>
> >          #Function wrapper
> >          A.expCallback = WINFUNCTYPE(None, c_int, c_int,  \
> >                            POINTER(Data_s))(A.Callback)
>
> >          #DLL call to register the local callback function
> >          DLLSetCallback(self.hID, A.SubID, EVENTID, A.expCallback)
>
> >      class A:
> >          #Local callback function
> >    @staticmethod
> >    def Callback(hID, SubID, Data):
> >               print 'I DON'T KNOW WHO I AM OR WHERE I CAME FROM!!'
> >               print 'BUT WITH hID, and SubID, I CAN FIGURE IT OUT'
> >               print 'IF I STORE A REFERENCE TO MYSELF IN A DICT'
> >               print 'USING KEY GENERATED FROM hID, SubID'
> >               pass
>
> > I'm not sure why they need to be static callbacks, but the DLL doc's
> > say "when using object based languages, such as c++, callback
> > functions must be declared as static functions and not instance
> > methods", and I couldn't get it to work without setting it up that
> > way. I could probably have them all be "classless" functions, but with
> > 100's of these, my namespace would be polluted up the wazoo, and I'd
> > still have the problem that they wouldn't have access to instance
> > methods / properties.
>
> The above code can't work with self, because you use
>
>   A.expCallback
>
> which at best can of course be a classmethod.
>
> You need to instead invoke DLLSetCallback with a bound method, like this
>
>   a = A()
>   DLLSetCallback(self.hID, A.SubID, EVENTID, a.expCallback)
>
> Also, the DLL-docs seem to refer to *C* or *C++*, where the concept of
> static functions is differently. If ctypes manages to get *some*
> callback passed, I'm 100% positive that it can pass *any* callable you
> like, including bound methods.
>
> Diez

Thinking about it some more, I believe I understand why it has to be
staticfunction. To use an bound method would require the wrapper to
include a reference to the instance as follows:

A.expCallback = WINFUNCTYPE(None, POINTER(A), c_int, c_int,  \
                                POINTER(Data_s))(a.Callback)

Since a = A(); a.foo() is really A.foo(self). The problem here is that
A is not a ctypes object and I can't change what arguments the DLL
uses in the callback in any case. Rewording my thoughts: a bound
method callback would require 'self' to be the first argument. I can
not make the DLL include 'self' as it doesn't know anything about the
objects in my program. Since I can't pass 'self', it has to be a
staticmethod.



More information about the Python-list mailing list