staticmethod and namespaces

Diez B. Roggisch deets at nospam.web.de
Fri Feb 26 10:41:27 EST 2010


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



More information about the Python-list mailing list