Using a metaclass on a class drived from another class implemented in CHow would a Python script running on Linux call a routine in a Python script running under Wine?Are static class variables possible?What are metaclasses in Python?How to randomly select an item from a list?Getting the class name of an instance?How do you read from stdin?class << self idiom in RubyPython class inherits objectWhy is reading lines from stdin much slower in C++ than Python?Flask + SQLAlchemy - custom metaclass to modify column setters (dynamic hybrid_property)Immutable attribute in python class and type check

What makes Ada the language of choice for the ISS's safety-critical systems?

What is the actual quality of machine translations?

How did old MS-DOS games utilize various graphic cards?

What ways have you found to get edits from non-LaTeX users?

How can I tell the difference between unmarked sugar and stevia?

Why did the Herschel Space Telescope need helium coolant?

Should I avoid hard-packed crusher dust trails with my hybrid?

Is it a problem if <h4>, <h5> and <h6> are smaller than regular text?

Preventing employees from either switching to competitors or opening their own business

What do abbreviations in movie scripts stand for?

Fixing obscure 8080 emulator bug?

What's up with this leaf?

Universal hash functions with homomorphic XOR property

Generate a Graeco-Latin square

How to signal to my players that the following part is supposed to be played on fast forward?

C++ Arduino IDE receiving garbled `char` from function

What is the highest possible temporary AC at level 1, without any help from others?

How to return a security deposit to a tenant

Frame failure sudden death?

Impedance ratio vs. SWR

Second (easy access) account in case my bank screws up

How to hide an urban landmark?

Pre-1972 sci-fi short story or novel: alien(?) tunnel where people try new moves and get destroyed if they're not the correct ones

How to forge a multi-part weapon?



Using a metaclass on a class drived from another class implemented in C


How would a Python script running on Linux call a routine in a Python script running under Wine?Are static class variables possible?What are metaclasses in Python?How to randomly select an item from a list?Getting the class name of an instance?How do you read from stdin?class << self idiom in RubyPython class inherits objectWhy is reading lines from stdin much slower in C++ than Python?Flask + SQLAlchemy - custom metaclass to modify column setters (dynamic hybrid_property)Immutable attribute in python class and type check






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








2















I am working on a ctypes drop-in-replacement / extension and ran into an issue I do not fully understand.



I am trying to build a class factory for call-back function decorators similar to CFUNCTYPE and WINFUNCTYPE. Both factories produce classes derived from ctypes._CFuncPtr. Like every ctypes function interface, they have properties like argtypes and restype. I want to extend the classes allowing an additional property named some_param and I thought, why not, let's try this with "getter" and "setter" methods - how hard can it be ...



Because I am trying to use "getter" and "setter" methods (@property) on a property of a class (NOT a property of objects), I ended up writing a metaclass. Because my class is derived from ctypes._CFuncPtr, I think my metaclass must be derived from ctypes._CFuncPtr.__class__ (I could be wrong here).



The example below works, sort of:



import ctypes

class a_class:

def b_function(self, some_param_parg):

class c_class_meta(ctypes._CFuncPtr.__class__):
def __init__(cls, *args):
super().__init__(*args) # no idea if this is good ...
cls._some_param_ = some_param_parg
@property
def some_param(cls):
return cls._some_param_
@some_param.setter
def some_param(cls, value):
if not isinstance(value, list):
raise TypeError('some_param must be a list')
cls._some_param_ = value

class c_class(ctypes._CFuncPtr, metaclass = c_class_meta):
_argtypes_ = ()
_restype_ = None
_flags_ = ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

return c_class

d_class = a_class().b_function([1, 2, 3])
print(d_class.some_param)
d_class.some_param = [2, 6]
print(d_class.some_param)
d_class.some_param = # Raises an error - as expected


So far so good - using the above any further does NOT work anymore. The following pseudo-code (if used on an actual function from a DLL or shared object) will fail - in fact, it will cause the CPython interpreter to segfault ...



some_routine = ctypes.windll.LoadLibrary('some.dll').some_routine
func_type = d_class(ctypes.c_int16, ctypes.c_int16) # similar to CFUNCTYPE/WINFUNCTYPE
func_type.some_param = [4, 5, 6] # my "special" property
some_routine.argtypes = (ctypes.c_int16, func_type)
@func_type
def demo(x):
return x - 1
some_routine(4, demo) # segfaults HERE!


I am not entirely sure what goes wrong. ctypes._CFuncPtr is implemented in C, which could be a relevant limitation ... I could also have made a mistake in the implementation of the metaclass. Can someone enlighten me?



(For additional context, I am working on this function.)










share|improve this question






























    2















    I am working on a ctypes drop-in-replacement / extension and ran into an issue I do not fully understand.



    I am trying to build a class factory for call-back function decorators similar to CFUNCTYPE and WINFUNCTYPE. Both factories produce classes derived from ctypes._CFuncPtr. Like every ctypes function interface, they have properties like argtypes and restype. I want to extend the classes allowing an additional property named some_param and I thought, why not, let's try this with "getter" and "setter" methods - how hard can it be ...



    Because I am trying to use "getter" and "setter" methods (@property) on a property of a class (NOT a property of objects), I ended up writing a metaclass. Because my class is derived from ctypes._CFuncPtr, I think my metaclass must be derived from ctypes._CFuncPtr.__class__ (I could be wrong here).



    The example below works, sort of:



    import ctypes

    class a_class:

    def b_function(self, some_param_parg):

    class c_class_meta(ctypes._CFuncPtr.__class__):
    def __init__(cls, *args):
    super().__init__(*args) # no idea if this is good ...
    cls._some_param_ = some_param_parg
    @property
    def some_param(cls):
    return cls._some_param_
    @some_param.setter
    def some_param(cls, value):
    if not isinstance(value, list):
    raise TypeError('some_param must be a list')
    cls._some_param_ = value

    class c_class(ctypes._CFuncPtr, metaclass = c_class_meta):
    _argtypes_ = ()
    _restype_ = None
    _flags_ = ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

    return c_class

    d_class = a_class().b_function([1, 2, 3])
    print(d_class.some_param)
    d_class.some_param = [2, 6]
    print(d_class.some_param)
    d_class.some_param = # Raises an error - as expected


    So far so good - using the above any further does NOT work anymore. The following pseudo-code (if used on an actual function from a DLL or shared object) will fail - in fact, it will cause the CPython interpreter to segfault ...



    some_routine = ctypes.windll.LoadLibrary('some.dll').some_routine
    func_type = d_class(ctypes.c_int16, ctypes.c_int16) # similar to CFUNCTYPE/WINFUNCTYPE
    func_type.some_param = [4, 5, 6] # my "special" property
    some_routine.argtypes = (ctypes.c_int16, func_type)
    @func_type
    def demo(x):
    return x - 1
    some_routine(4, demo) # segfaults HERE!


    I am not entirely sure what goes wrong. ctypes._CFuncPtr is implemented in C, which could be a relevant limitation ... I could also have made a mistake in the implementation of the metaclass. Can someone enlighten me?



    (For additional context, I am working on this function.)










    share|improve this question


























      2












      2








      2








      I am working on a ctypes drop-in-replacement / extension and ran into an issue I do not fully understand.



      I am trying to build a class factory for call-back function decorators similar to CFUNCTYPE and WINFUNCTYPE. Both factories produce classes derived from ctypes._CFuncPtr. Like every ctypes function interface, they have properties like argtypes and restype. I want to extend the classes allowing an additional property named some_param and I thought, why not, let's try this with "getter" and "setter" methods - how hard can it be ...



      Because I am trying to use "getter" and "setter" methods (@property) on a property of a class (NOT a property of objects), I ended up writing a metaclass. Because my class is derived from ctypes._CFuncPtr, I think my metaclass must be derived from ctypes._CFuncPtr.__class__ (I could be wrong here).



      The example below works, sort of:



      import ctypes

      class a_class:

      def b_function(self, some_param_parg):

      class c_class_meta(ctypes._CFuncPtr.__class__):
      def __init__(cls, *args):
      super().__init__(*args) # no idea if this is good ...
      cls._some_param_ = some_param_parg
      @property
      def some_param(cls):
      return cls._some_param_
      @some_param.setter
      def some_param(cls, value):
      if not isinstance(value, list):
      raise TypeError('some_param must be a list')
      cls._some_param_ = value

      class c_class(ctypes._CFuncPtr, metaclass = c_class_meta):
      _argtypes_ = ()
      _restype_ = None
      _flags_ = ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

      return c_class

      d_class = a_class().b_function([1, 2, 3])
      print(d_class.some_param)
      d_class.some_param = [2, 6]
      print(d_class.some_param)
      d_class.some_param = # Raises an error - as expected


      So far so good - using the above any further does NOT work anymore. The following pseudo-code (if used on an actual function from a DLL or shared object) will fail - in fact, it will cause the CPython interpreter to segfault ...



      some_routine = ctypes.windll.LoadLibrary('some.dll').some_routine
      func_type = d_class(ctypes.c_int16, ctypes.c_int16) # similar to CFUNCTYPE/WINFUNCTYPE
      func_type.some_param = [4, 5, 6] # my "special" property
      some_routine.argtypes = (ctypes.c_int16, func_type)
      @func_type
      def demo(x):
      return x - 1
      some_routine(4, demo) # segfaults HERE!


      I am not entirely sure what goes wrong. ctypes._CFuncPtr is implemented in C, which could be a relevant limitation ... I could also have made a mistake in the implementation of the metaclass. Can someone enlighten me?



      (For additional context, I am working on this function.)










      share|improve this question
















      I am working on a ctypes drop-in-replacement / extension and ran into an issue I do not fully understand.



      I am trying to build a class factory for call-back function decorators similar to CFUNCTYPE and WINFUNCTYPE. Both factories produce classes derived from ctypes._CFuncPtr. Like every ctypes function interface, they have properties like argtypes and restype. I want to extend the classes allowing an additional property named some_param and I thought, why not, let's try this with "getter" and "setter" methods - how hard can it be ...



      Because I am trying to use "getter" and "setter" methods (@property) on a property of a class (NOT a property of objects), I ended up writing a metaclass. Because my class is derived from ctypes._CFuncPtr, I think my metaclass must be derived from ctypes._CFuncPtr.__class__ (I could be wrong here).



      The example below works, sort of:



      import ctypes

      class a_class:

      def b_function(self, some_param_parg):

      class c_class_meta(ctypes._CFuncPtr.__class__):
      def __init__(cls, *args):
      super().__init__(*args) # no idea if this is good ...
      cls._some_param_ = some_param_parg
      @property
      def some_param(cls):
      return cls._some_param_
      @some_param.setter
      def some_param(cls, value):
      if not isinstance(value, list):
      raise TypeError('some_param must be a list')
      cls._some_param_ = value

      class c_class(ctypes._CFuncPtr, metaclass = c_class_meta):
      _argtypes_ = ()
      _restype_ = None
      _flags_ = ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

      return c_class

      d_class = a_class().b_function([1, 2, 3])
      print(d_class.some_param)
      d_class.some_param = [2, 6]
      print(d_class.some_param)
      d_class.some_param = # Raises an error - as expected


      So far so good - using the above any further does NOT work anymore. The following pseudo-code (if used on an actual function from a DLL or shared object) will fail - in fact, it will cause the CPython interpreter to segfault ...



      some_routine = ctypes.windll.LoadLibrary('some.dll').some_routine
      func_type = d_class(ctypes.c_int16, ctypes.c_int16) # similar to CFUNCTYPE/WINFUNCTYPE
      func_type.some_param = [4, 5, 6] # my "special" property
      some_routine.argtypes = (ctypes.c_int16, func_type)
      @func_type
      def demo(x):
      return x - 1
      some_routine(4, demo) # segfaults HERE!


      I am not entirely sure what goes wrong. ctypes._CFuncPtr is implemented in C, which could be a relevant limitation ... I could also have made a mistake in the implementation of the metaclass. Can someone enlighten me?



      (For additional context, I am working on this function.)







      python python-3.x ctypes metaclass






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 24 at 17:33







      s-m-e

















      asked Mar 24 at 17:20









      s-m-es-m-e

      1,57521839




      1,57521839






















          1 Answer
          1






          active

          oldest

          votes


















          1














          Maybe ctypes metaclasses simply won't work nicely being subclasses - since it is itself written in C, it may bypass the routes inheritance imposes for some shortcuts and end up in failures.



          Ideally this "bad behavior" would have to be properly documented, filled as bugs against CPython's ctypes and fixed - to my knowledge there are not many people who can fix ctypes bugs.



          On the other hand, having a metaclass just because you want a property-like attribute at class level is overkill.



          Python's property itself is just pre-made, very useful builtin class that implements the descriptor protocol. Any class you create yourself that implements proper __get__ and __set__ methods can replace "property" (and often, when logic is shared across property-attributes, leads to shorter, non duplicated code)



          On a second though, unfortunately, descriptor setters will only work for instances, not for classes (which makes sense, since doing cls.attr will already get you the special code-guarded value, and there is no way a __set__ method could be called on it)



          So, if you could work with "manually" setting the values in the cls.__dict__ and putting your logic in the __get__ attribute, you could do:



          PREFIX = "_cls_prop_"

          class ClsProperty:
          def __set_name__(self, owner, name):
          self.name = name

          def __get__(self, instance, owner):
          value = owner.__dict__.get(PREFIX + self.name)
          # Logic to transform/check value goes here:
          if not isinstance(value, list):
          raise TypeError('some_param must be a list')
          return value


          def b_function(some_param_arg):

          class c_class(ctypes._CFuncPtr):
          _argtypes_ = ()
          _restype_ = None
          _flags_ = 0 # ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

          _some_param_ = ClsProperty()

          setattr(c_class, PREFIX + "_some_param_", some_param_arg)

          return c_class


          d_class = b_function([1, 2, 3])
          print(d_class._some_param_)
          d_class._some_param_ = [1, 2]
          print(d_class._some_param_)


          If that does not work, I don't think other approaches trying to extend CTypes metaclass will work anyway, but if you want a try, instead of a "meta-property", you might try to customize the metaclass' __setitem__ instead, to do your parameter checking, instead of using property.






          share|improve this answer

























          • Thanks a lot for the answer. I thought I would not get one at all. Actually, it was an answer of yours to a question of mine that inspired the whole mad project, so thanks for that too ;) I (mildly) edited the code in your answer to reflect how it should look like AFAIK (?), but it still does not work. The line c_class.__dict__[PREFIX + '_some_param_'] = some_param_arg fails with TypeError: 'mappingproxy' object does not support item assignment. I have not yet managed to make some sense of it. What do I have to do to complete the example?

            – s-m-e
            Mar 28 at 21:10











          • Yes - sorry for that - setattr(c_class, PREFIX + "_some_param_", some_param_arg) should work there.

            – jsbueno
            Mar 29 at 19:13











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55326437%2fusing-a-metaclass-on-a-class-drived-from-another-class-implemented-in-c%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Maybe ctypes metaclasses simply won't work nicely being subclasses - since it is itself written in C, it may bypass the routes inheritance imposes for some shortcuts and end up in failures.



          Ideally this "bad behavior" would have to be properly documented, filled as bugs against CPython's ctypes and fixed - to my knowledge there are not many people who can fix ctypes bugs.



          On the other hand, having a metaclass just because you want a property-like attribute at class level is overkill.



          Python's property itself is just pre-made, very useful builtin class that implements the descriptor protocol. Any class you create yourself that implements proper __get__ and __set__ methods can replace "property" (and often, when logic is shared across property-attributes, leads to shorter, non duplicated code)



          On a second though, unfortunately, descriptor setters will only work for instances, not for classes (which makes sense, since doing cls.attr will already get you the special code-guarded value, and there is no way a __set__ method could be called on it)



          So, if you could work with "manually" setting the values in the cls.__dict__ and putting your logic in the __get__ attribute, you could do:



          PREFIX = "_cls_prop_"

          class ClsProperty:
          def __set_name__(self, owner, name):
          self.name = name

          def __get__(self, instance, owner):
          value = owner.__dict__.get(PREFIX + self.name)
          # Logic to transform/check value goes here:
          if not isinstance(value, list):
          raise TypeError('some_param must be a list')
          return value


          def b_function(some_param_arg):

          class c_class(ctypes._CFuncPtr):
          _argtypes_ = ()
          _restype_ = None
          _flags_ = 0 # ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

          _some_param_ = ClsProperty()

          setattr(c_class, PREFIX + "_some_param_", some_param_arg)

          return c_class


          d_class = b_function([1, 2, 3])
          print(d_class._some_param_)
          d_class._some_param_ = [1, 2]
          print(d_class._some_param_)


          If that does not work, I don't think other approaches trying to extend CTypes metaclass will work anyway, but if you want a try, instead of a "meta-property", you might try to customize the metaclass' __setitem__ instead, to do your parameter checking, instead of using property.






          share|improve this answer

























          • Thanks a lot for the answer. I thought I would not get one at all. Actually, it was an answer of yours to a question of mine that inspired the whole mad project, so thanks for that too ;) I (mildly) edited the code in your answer to reflect how it should look like AFAIK (?), but it still does not work. The line c_class.__dict__[PREFIX + '_some_param_'] = some_param_arg fails with TypeError: 'mappingproxy' object does not support item assignment. I have not yet managed to make some sense of it. What do I have to do to complete the example?

            – s-m-e
            Mar 28 at 21:10











          • Yes - sorry for that - setattr(c_class, PREFIX + "_some_param_", some_param_arg) should work there.

            – jsbueno
            Mar 29 at 19:13















          1














          Maybe ctypes metaclasses simply won't work nicely being subclasses - since it is itself written in C, it may bypass the routes inheritance imposes for some shortcuts and end up in failures.



          Ideally this "bad behavior" would have to be properly documented, filled as bugs against CPython's ctypes and fixed - to my knowledge there are not many people who can fix ctypes bugs.



          On the other hand, having a metaclass just because you want a property-like attribute at class level is overkill.



          Python's property itself is just pre-made, very useful builtin class that implements the descriptor protocol. Any class you create yourself that implements proper __get__ and __set__ methods can replace "property" (and often, when logic is shared across property-attributes, leads to shorter, non duplicated code)



          On a second though, unfortunately, descriptor setters will only work for instances, not for classes (which makes sense, since doing cls.attr will already get you the special code-guarded value, and there is no way a __set__ method could be called on it)



          So, if you could work with "manually" setting the values in the cls.__dict__ and putting your logic in the __get__ attribute, you could do:



          PREFIX = "_cls_prop_"

          class ClsProperty:
          def __set_name__(self, owner, name):
          self.name = name

          def __get__(self, instance, owner):
          value = owner.__dict__.get(PREFIX + self.name)
          # Logic to transform/check value goes here:
          if not isinstance(value, list):
          raise TypeError('some_param must be a list')
          return value


          def b_function(some_param_arg):

          class c_class(ctypes._CFuncPtr):
          _argtypes_ = ()
          _restype_ = None
          _flags_ = 0 # ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

          _some_param_ = ClsProperty()

          setattr(c_class, PREFIX + "_some_param_", some_param_arg)

          return c_class


          d_class = b_function([1, 2, 3])
          print(d_class._some_param_)
          d_class._some_param_ = [1, 2]
          print(d_class._some_param_)


          If that does not work, I don't think other approaches trying to extend CTypes metaclass will work anyway, but if you want a try, instead of a "meta-property", you might try to customize the metaclass' __setitem__ instead, to do your parameter checking, instead of using property.






          share|improve this answer

























          • Thanks a lot for the answer. I thought I would not get one at all. Actually, it was an answer of yours to a question of mine that inspired the whole mad project, so thanks for that too ;) I (mildly) edited the code in your answer to reflect how it should look like AFAIK (?), but it still does not work. The line c_class.__dict__[PREFIX + '_some_param_'] = some_param_arg fails with TypeError: 'mappingproxy' object does not support item assignment. I have not yet managed to make some sense of it. What do I have to do to complete the example?

            – s-m-e
            Mar 28 at 21:10











          • Yes - sorry for that - setattr(c_class, PREFIX + "_some_param_", some_param_arg) should work there.

            – jsbueno
            Mar 29 at 19:13













          1












          1








          1







          Maybe ctypes metaclasses simply won't work nicely being subclasses - since it is itself written in C, it may bypass the routes inheritance imposes for some shortcuts and end up in failures.



          Ideally this "bad behavior" would have to be properly documented, filled as bugs against CPython's ctypes and fixed - to my knowledge there are not many people who can fix ctypes bugs.



          On the other hand, having a metaclass just because you want a property-like attribute at class level is overkill.



          Python's property itself is just pre-made, very useful builtin class that implements the descriptor protocol. Any class you create yourself that implements proper __get__ and __set__ methods can replace "property" (and often, when logic is shared across property-attributes, leads to shorter, non duplicated code)



          On a second though, unfortunately, descriptor setters will only work for instances, not for classes (which makes sense, since doing cls.attr will already get you the special code-guarded value, and there is no way a __set__ method could be called on it)



          So, if you could work with "manually" setting the values in the cls.__dict__ and putting your logic in the __get__ attribute, you could do:



          PREFIX = "_cls_prop_"

          class ClsProperty:
          def __set_name__(self, owner, name):
          self.name = name

          def __get__(self, instance, owner):
          value = owner.__dict__.get(PREFIX + self.name)
          # Logic to transform/check value goes here:
          if not isinstance(value, list):
          raise TypeError('some_param must be a list')
          return value


          def b_function(some_param_arg):

          class c_class(ctypes._CFuncPtr):
          _argtypes_ = ()
          _restype_ = None
          _flags_ = 0 # ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

          _some_param_ = ClsProperty()

          setattr(c_class, PREFIX + "_some_param_", some_param_arg)

          return c_class


          d_class = b_function([1, 2, 3])
          print(d_class._some_param_)
          d_class._some_param_ = [1, 2]
          print(d_class._some_param_)


          If that does not work, I don't think other approaches trying to extend CTypes metaclass will work anyway, but if you want a try, instead of a "meta-property", you might try to customize the metaclass' __setitem__ instead, to do your parameter checking, instead of using property.






          share|improve this answer















          Maybe ctypes metaclasses simply won't work nicely being subclasses - since it is itself written in C, it may bypass the routes inheritance imposes for some shortcuts and end up in failures.



          Ideally this "bad behavior" would have to be properly documented, filled as bugs against CPython's ctypes and fixed - to my knowledge there are not many people who can fix ctypes bugs.



          On the other hand, having a metaclass just because you want a property-like attribute at class level is overkill.



          Python's property itself is just pre-made, very useful builtin class that implements the descriptor protocol. Any class you create yourself that implements proper __get__ and __set__ methods can replace "property" (and often, when logic is shared across property-attributes, leads to shorter, non duplicated code)



          On a second though, unfortunately, descriptor setters will only work for instances, not for classes (which makes sense, since doing cls.attr will already get you the special code-guarded value, and there is no way a __set__ method could be called on it)



          So, if you could work with "manually" setting the values in the cls.__dict__ and putting your logic in the __get__ attribute, you could do:



          PREFIX = "_cls_prop_"

          class ClsProperty:
          def __set_name__(self, owner, name):
          self.name = name

          def __get__(self, instance, owner):
          value = owner.__dict__.get(PREFIX + self.name)
          # Logic to transform/check value goes here:
          if not isinstance(value, list):
          raise TypeError('some_param must be a list')
          return value


          def b_function(some_param_arg):

          class c_class(ctypes._CFuncPtr):
          _argtypes_ = ()
          _restype_ = None
          _flags_ = 0 # ctypes._FUNCFLAG_STDCALL # change for CFUNCTYPE or WINFUNCTYPE etc ...

          _some_param_ = ClsProperty()

          setattr(c_class, PREFIX + "_some_param_", some_param_arg)

          return c_class


          d_class = b_function([1, 2, 3])
          print(d_class._some_param_)
          d_class._some_param_ = [1, 2]
          print(d_class._some_param_)


          If that does not work, I don't think other approaches trying to extend CTypes metaclass will work anyway, but if you want a try, instead of a "meta-property", you might try to customize the metaclass' __setitem__ instead, to do your parameter checking, instead of using property.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 29 at 19:14

























          answered Mar 25 at 15:00









          jsbuenojsbueno

          58.5k684133




          58.5k684133












          • Thanks a lot for the answer. I thought I would not get one at all. Actually, it was an answer of yours to a question of mine that inspired the whole mad project, so thanks for that too ;) I (mildly) edited the code in your answer to reflect how it should look like AFAIK (?), but it still does not work. The line c_class.__dict__[PREFIX + '_some_param_'] = some_param_arg fails with TypeError: 'mappingproxy' object does not support item assignment. I have not yet managed to make some sense of it. What do I have to do to complete the example?

            – s-m-e
            Mar 28 at 21:10











          • Yes - sorry for that - setattr(c_class, PREFIX + "_some_param_", some_param_arg) should work there.

            – jsbueno
            Mar 29 at 19:13

















          • Thanks a lot for the answer. I thought I would not get one at all. Actually, it was an answer of yours to a question of mine that inspired the whole mad project, so thanks for that too ;) I (mildly) edited the code in your answer to reflect how it should look like AFAIK (?), but it still does not work. The line c_class.__dict__[PREFIX + '_some_param_'] = some_param_arg fails with TypeError: 'mappingproxy' object does not support item assignment. I have not yet managed to make some sense of it. What do I have to do to complete the example?

            – s-m-e
            Mar 28 at 21:10











          • Yes - sorry for that - setattr(c_class, PREFIX + "_some_param_", some_param_arg) should work there.

            – jsbueno
            Mar 29 at 19:13
















          Thanks a lot for the answer. I thought I would not get one at all. Actually, it was an answer of yours to a question of mine that inspired the whole mad project, so thanks for that too ;) I (mildly) edited the code in your answer to reflect how it should look like AFAIK (?), but it still does not work. The line c_class.__dict__[PREFIX + '_some_param_'] = some_param_arg fails with TypeError: 'mappingproxy' object does not support item assignment. I have not yet managed to make some sense of it. What do I have to do to complete the example?

          – s-m-e
          Mar 28 at 21:10





          Thanks a lot for the answer. I thought I would not get one at all. Actually, it was an answer of yours to a question of mine that inspired the whole mad project, so thanks for that too ;) I (mildly) edited the code in your answer to reflect how it should look like AFAIK (?), but it still does not work. The line c_class.__dict__[PREFIX + '_some_param_'] = some_param_arg fails with TypeError: 'mappingproxy' object does not support item assignment. I have not yet managed to make some sense of it. What do I have to do to complete the example?

          – s-m-e
          Mar 28 at 21:10













          Yes - sorry for that - setattr(c_class, PREFIX + "_some_param_", some_param_arg) should work there.

          – jsbueno
          Mar 29 at 19:13





          Yes - sorry for that - setattr(c_class, PREFIX + "_some_param_", some_param_arg) should work there.

          – jsbueno
          Mar 29 at 19:13



















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55326437%2fusing-a-metaclass-on-a-class-drived-from-another-class-implemented-in-c%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

          Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

          Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript