From denis.akhiyarov at gmail.com Fri Aug 18 00:05:24 2017 From: denis.akhiyarov at gmail.com (Denis Akhiyarov) Date: Thu, 17 Aug 2017 23:05:24 -0500 Subject: [Python.NET] Inheriting from abstract .NET class In-Reply-To: References: <172ece7de07246a2a7f30d75f9aa0bb4@ex2013.orga-test.local> <7d1b1b6d0e5e47f59819d686b5606dbb@ex2013.orga-test.local> Message-ID: Hi Henning, Your question about abstract classes in pythonnet reposted at stackoverflow received a lot of attention recently: https://stackoverflow.com/questions/39659469/how-to-inherit-from-an-abstract-base-class-written-in-c-sharp Thanks, Denis On Tue, Sep 27, 2016 at 11:56 AM, Denis Akhiyarov wrote: > Henning, > > It is very questionable if "protected" should be available for overriding > in Python, since we are not really doing compile time overriding in a .NET > class with all sorts of differences in class compilation vs runtime > emission. > > But as a quick workaround you can add protected in this method in > pythonnet: > > private static void AddVirtualMethod(MethodInfo method, Type baseType, TypeBuilder typeBuilder) > > Let us know about the result. > > Cheers, > Denis > > On Tue, Sep 27, 2016 at 2:49 AM, Henning Moeller > wrote: > >> Hi Denis, >> >> >> >> thank you again. That helped a lot. >> >> >> >> But ? I?m sorry to bother you again. In the classes I really have to use, >> some of the virtual methods are protected. Those are not resolved by >> pythonnet. Only public virtual is recognized and overridden by the >> inherited class. See the (only slightly) altered example: >> >> >> >> namespace PythonBaseClass >> >> { >> >> using System; >> >> >> >> public class Door >> >> { >> >> public virtual void Open() >> >> { >> >> if (!IsOpen()) >> >> Toggle(); >> >> } >> >> >> >> public virtual void Close() >> >> { >> >> if (IsOpen()) >> >> Toggle(); >> >> } >> >> >> >> public virtual bool IsOpen() >> >> { >> >> Console.WriteLine("Door.IsOpen()"); >> >> return false; >> >> } >> >> >> >> *protected* virtual void Toggle() >> >> { >> >> Console.WriteLine("Door.Toggle()"); >> >> } >> >> } >> >> } >> >> >> >> The Python code has just been altered so that the namespace is properly >> set. Running the example comes with the following output: >> >> >> >> Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 >> 32 bit (Intel)] on win32 >> >> Type "help", "copyright", "credits" or "license" for more information. >> >> >>> from PythonInheritedClass import * >> >> >>> d = StringDoor() >> >> >>> d.status >> >> 'closed' >> >> >>> d.Open() >> >> StringDoor.IsOpen() >> >> *Door.Toggle()* >> >> >>> >> >> >> >> Any ideas? This looks a little bit more ?doable? than the abstract thing. >> >> >> >> BR, >> >> >> >> Henning >> >> >> >> *From:* PythonDotNet [mailto:pythondotnet-bounces+hmoeller= >> comprion.com at python.org] *On Behalf Of *Denis Akhiyarov >> *Sent:* Montag, 26. September 2016 20:16 >> *To:* A list for users and developers of Python for .NET < >> pythondotnet at python.org> >> *Subject:* Re: [Python.NET] Inheriting from abstract .NET class >> >> >> >> Hi Henning, >> >> >> >> This feature was implemented by @tonyroberts in 2013 and is tested in CI >> with test_subclass.py file. >> >> >> >> According to these tests, the missing piece in your code is defining >> explicitly __namespace__ on the .NET class derived in Python: >> >> >> >> In [11]: class StringDoor1(Door): >> >> ....: __namespace__ = "PythonBaseClass" >> >> ....: def __init__(self): >> >> ....: self.status = "closed" >> >> ....: >> >> ....: def IsOpen(self): >> >> ....: print "StringDoor.IsOpen()" >> >> ....: return self.status == "open" >> >> ....: >> >> ....: def Toggle(self): >> >> ....: print "StringDoor.Toggle()" >> >> ....: if self.status == "open": >> >> ....: self.status = "closed" >> >> ....: else: >> >> ....: self.status = "open" >> >> >> >> In [12]: d = StringDoor1() >> >> >> >> In [13]: d.status >> >> Out[13]: 'closed' >> >> >> >> In [14]: d.Open() >> >> StringDoor.IsOpen() >> >> StringDoor.Toggle() >> >> >> >> In [15]: d.status >> >> Out[15]: 'open' >> >> >> >> >> >> >> >> Thanks, >> >> Denis >> >> >> >> On Mon, Sep 26, 2016 at 9:19 AM, Henning Moeller >> wrote: >> >> Hi Denis, >> >> >> >> Thanks for your fast response. Sounds completely reasonable to me. And >> this has not been too much of an issue for me. >> >> >> >> I got rid of the abstract base class simply by providing an ?empty? >> implementation and using a non-abstract base class. No need for meta >> classes any more. This way, I got rid of error messages. Great! >> >> >> >> Unfortunately, there seem to be an issue when calling a virtual method >> inside the C# implementation. Even when overriding this virtual method in >> Python, it?s still the base class? implementation which is called. >> >> >> >> See the new simple base class defined in C#: >> >> >> >> namespace PythonBaseClass >> >> { >> >> using System; >> >> >> >> public class Door >> >> { >> >> public virtual void Open() >> >> { >> >> if (!IsOpen()) >> >> Toggle(); >> >> } >> >> >> >> public virtual void Close() >> >> { >> >> if (IsOpen()) >> >> Toggle(); >> >> } >> >> >> >> public virtual bool IsOpen() >> >> { >> >> Console.WriteLine("Door.IsOpen()"); >> >> return false; >> >> } >> >> >> >> public virtual void Toggle() >> >> { >> >> Console.WriteLine("Door.Toggle()"); >> >> } >> >> } >> >> } >> >> >> >> The consuming Python code now looks like this: >> >> >> >> import clr >> >> from PythonBaseClass import Door >> >> >> >> class StringDoor(Door): >> >> def __init__(self): >> >> self.status = "closed" >> >> >> >> def IsOpen(self): >> >> print "StringDoor.IsOpen()" >> >> return self.status == "open" >> >> >> >> def Toggle(self): >> >> print "StringDoor.Toggle()" >> >> if self.status == "open": >> >> self.status = "closed" >> >> else: >> >> self.status = "open" >> >> >> >> But the output does not look like expected: >> >> >> >> Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 >> 32 bit (Intel)] on win32 >> >> Type "help", "copyright", "credits" or "license" for more information. >> >> >>> from PythonInheritedClass import StringDoor >> >> >>> d = StringDoor() >> >> >>> d.status >> >> 'closed' >> >> >>> d.Open() >> >> *Door.IsOpen()* >> >> *Door.Toggle()* >> >> >>> d.status >> >> *'closed'* >> >> >>> >> >> >> >> From my understanding, the output should rather read ? >> StringDoor.()? instead of ?Door.()?. Obviously, >> only the base implementation is called but the overridden methods are >> ignored. >> >> >> >> Also a limitation of inheriting C# classes in pythonnet? >> >> >> >> BR, >> >> >> >> Henning >> >> >> >> *From:* PythonDotNet [mailto:pythondotnet-bounces+hmoeller= >> comprion.com at python.org] *On Behalf Of *Denis Akhiyarov >> *Sent:* Donnerstag, 22. September 2016 19:38 >> *To:* A list for users and developers of Python for .NET < >> pythondotnet at python.org> >> *Subject:* Re: [Python.NET] Inheriting from abstract .NET class >> >> >> >> You are not a "Python n00b" based on metaclass usage! >> >> >> >> My recommendation is to keep simple integration layer between CPython and >> .NET, hence metaclasses were/are not supported. >> >> >> >> But contributions are welcome! Although I expect this to be a tremendous >> undertaking based on reviewing multiple sources. >> >> >> >> Note that metaclass is a very different low-level concept from >> higher-level abstract classes in .NET, hence direct mapping (e.g. >> `.register()` ) is not feasible. >> >> >> >> Thanks, >> >> Denis >> >> >> >> On Thu, Sep 22, 2016 at 10:04 AM, Henning Moeller >> wrote: >> >> Hello out there, >> >> >> >> I?m trying to inherit from an abstract .NET base class in Python (2.7). >> I?m a Python n00b but from what I understood? >> >> >> >> Here?s what I managed to do in Python only and which works fine: >> >> >> >> [File: room.py] ------- >> >> import abc >> >> >> >> class Room(object): >> >> def __init__(self, door): >> >> self.door = door >> >> >> >> def open(self): >> >> self.door.open() >> >> >> >> def close(self): >> >> self.door.close() >> >> >> >> def is_open(self): >> >> return self.door.is_open() >> >> >> >> class Door(object): >> >> __metaclass__ = abc.ABCMeta >> >> >> >> def open(self): >> >> if not self.is_open(): >> >> self.toggle() >> >> >> >> def close(self): >> >> if self.is_open(): >> >> self.toggle() >> >> >> >> @abc.abstractmethod >> >> def is_open(self): >> >> pass >> >> >> >> @abc.abstractmethod >> >> def toggle(self): >> >> pass >> >> >> >> class StringDoor(Door): >> >> def __init__(self): >> >> self.status = "closed" >> >> >> >> def is_open(self): >> >> return self.status == "open" >> >> >> >> def toggle(self): >> >> if self.status == "open": >> >> self.status = "closed" >> >> else: >> >> self.status = "open" >> >> >> >> class BooleanDoor(Door): >> >> def __init__(self): >> >> self.status = True >> >> >> >> def is_open(self): >> >> return self.status >> >> >> >> def toggle(self): >> >> self.status = not (self.status) >> >> >> >> Door.register(StringDoor) >> >> Door.register(BooleanDoor) >> >> ------- >> >> >> >> Now, all I did was to replace the abstract base class Door by a C# >> representation: >> >> >> >> [File: PythonAbstractBaseClass.dll] ------- >> >> namespace PythonAbstractBaseClass >> >> { >> >> public abstract class Door >> >> { >> >> public virtual void Open() >> >> { >> >> if (!IsOpen()) >> >> Toggle(); >> >> } >> >> >> >> public virtual void Close() >> >> { >> >> if (IsOpen()) >> >> Toggle(); >> >> } >> >> >> >> public abstract bool IsOpen(); >> >> public abstract void Toggle(); >> >> } >> >> } >> >> ------- >> >> >> >> Removing Door from the Python part and importing it from the .NET >> assembly instead, I end up with this: >> >> >> >> [File: room2.py] ------- >> >> import clr >> >> import abc >> >> from PythonAbstractBaseClass import Door >> >> >> >> class Room(object): >> >> def __init__(self, door): >> >> self.door = door >> >> >> >> def open(self): >> >> self.door.open() >> >> >> >> def close(self): >> >> self.door.close() >> >> >> >> def is_open(self): >> >> return self.door.is_open() >> >> >> >> class StringDoor(Door): >> >> def __init__(self): >> >> self.status = "closed" >> >> >> >> def is_open(self): >> >> return self.status == "open" >> >> >> >> def toggle(self): >> >> if self.status == "open": >> >> self.status = "closed" >> >> else: >> >> self.status = "open" >> >> >> >> class BooleanDoor(Door): >> >> def __init__(self): >> >> self.status = True >> >> >> >> def is_open(self): >> >> return self.status >> >> >> >> def toggle(self): >> >> self.status = not (self.status) >> >> >> >> Door.register(StringDoor) >> >> Door.register(BooleanDoor) >> >> ------- >> >> >> >> But this fails with the following error message: >> >> >> >> Door.register(StringDoor) >> >> AttributeError: type object 'Door' has no attribute 'register' >> >> >> >> From what I understood about abc.ABCMeta, this metaclass contributes the >> ?register? method. It seems that abstract C# classes do not come with the >> same metaclass. They instead come with metaclass ?CLR Metatype? which >> obviously does not provide ?register?. >> >> >> >> But if I drop the call to ?register?, on instantiating one of the derived >> classes, I receive the error message >> >> >> >> sdoor = StringDoor() >> >> TypeError: cannot instantiate abstract class >> >> >> >> Is there a way to inherit from an abstract .NET class or is this is >> missing feature? >> >> >> >> Thanks in advance, >> >> >> >> Henning >> >> >> >> >> _________________________________________________ >> Python.NET mailing list - PythonDotNet at python.org >> https://mail.python.org/mailman/listinfo/pythondotnet >> >> >> >> >> _________________________________________________ >> Python.NET mailing list - PythonDotNet at python.org >> https://mail.python.org/mailman/listinfo/pythondotnet >> >> >> >> _________________________________________________ >> Python.NET mailing list - PythonDotNet at python.org >> https://mail.python.org/mailman/listinfo/pythondotnet >> > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From homerun4711 at gmail.com Thu Aug 24 08:40:41 2017 From: homerun4711 at gmail.com (Walter White) Date: Thu, 24 Aug 2017 14:40:41 +0200 Subject: [Python.NET] How to cast a pointer to a Python cffi struct to System.IntPtr (.NET, pythonnet)? Message-ID: Hello, I have a question and hope you can help me. I already asked on stackoverflow but no solution so far. https://stackoverflow.com/questions/45860493/how-to- cast-a-pointer-to-a-python-cffi-struct-to-system-intptr-net Kind regards, Joe -------------- next part -------------- An HTML attachment was scrubbed... URL: