www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - pyd: implementing __hash__ and __str__ for PyD wrapped classes

reply harfel <dadapapa gmail.com> writes:
Dear all,

Relatively new to D in general and PyD in particular, I am trying 
to wrap some D classes I wrote for use in Python.

Following the documentation and code examples, I got the basic 
functionality working. However, I am struggling with implementing 
the magic functions __str__ and __hash__ of the extension class. 
My current approach was to implement them as ordinary member 
functions:


extern(C) void PydMain() {
	module_init();

	// Reaction
	wrap_class!(PyReaction,
		PyName!"Reaction",
		Init!(MultiSet, MultiSet),
		Property!(PyReaction.reactants),
		Property!(PyReaction.products),
		Repr!(PyReaction.repr),
		Def!(PyReaction.py_str, PyName!"__str__"),   // XXX needs slot
		Def!(PyReaction.py_hash, PyName!"__hash__"), // XXX needs slot
	)();
}

but this does not work. In Python:

Python 2.7.12+ (default, Sep 17 2016, 12:08:02)
[GCC 6.2.0 20160914] on linux2
Type "help", "copyright", "credits" or "license" for more 
information.
 from teest_module import *
 r=Reaction({'a':1, 'b':1}, {'ab':1})
 r.__hash__
<built-in method __hash__ of stochcalc.Reaction object at 0x7fc1c7f4a080>
 r.__hash__()
1430289695L
 hash(r)
8779391257096 According to related post for C++/SWIG (http://stackoverflow.com/questions/25199233/str-not-called-when-printing-c-class-wrapped-fo -python-with-swig), the reason is that these magic methods need to be implemented as slots, rather than ordinary member functions. Is there a way to declare these slots in PyD? I noticed that Repr does this for __repr__ and the operator overloads do this of course for their respective slots, but I could not find anything for __hash__ and __str__. Any ideas? Thanks!
Apr 05 2017
parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 5 April 2017 at 09:31:09 UTC, harfel wrote:
 Dear all,

 Relatively new to D in general and PyD in particular, I am 
 trying to wrap some D classes I wrote for use in Python.

 Following the documentation and code examples, I got the basic 
 functionality working. However, I am struggling with 
 implementing the magic functions __str__ and __hash__ of the 
 extension class. My current approach was to implement them as 
 ordinary member functions:


 extern(C) void PydMain() {
 	module_init();

 	// Reaction
 	wrap_class!(PyReaction,
 		PyName!"Reaction",
 		Init!(MultiSet, MultiSet),
 		Property!(PyReaction.reactants),
 		Property!(PyReaction.products),
 		Repr!(PyReaction.repr),
 		Def!(PyReaction.py_str, PyName!"__str__"),   // XXX needs slot
 		Def!(PyReaction.py_hash, PyName!"__hash__"), // XXX needs slot
 	)();
 }

 but this does not work. In Python:

 Python 2.7.12+ (default, Sep 17 2016, 12:08:02)
 [GCC 6.2.0 20160914] on linux2
 Type "help", "copyright", "credits" or "license" for more 
 information.
 from teest_module import *
 r=Reaction({'a':1, 'b':1}, {'ab':1})
 r.__hash__
<built-in method __hash__ of stochcalc.Reaction object at 0x7fc1c7f4a080>
 r.__hash__()
1430289695L
 hash(r)
8779391257096 According to related post for C++/SWIG (http://stackoverflow.com/questions/25199233/str-not-called-when-printing-c-class-wrapped-fo -python-with-swig), the reason is that these magic methods need to be implemented as slots, rather than ordinary member functions. Is there a way to declare these slots in PyD? I noticed that Repr does this for __repr__ and the operator overloads do this of course for their respective slots, but I could not find anything for __hash__ and __str__. Any ideas? Thanks!
I haven't chased the source but most likely __hash__ and __str__ will be "magically" generated from toHash() and toString() respectively (both methods of Object, see:https://dlang.org/phobos/object.html#.Object).
Apr 05 2017
parent harfel <dadapapa gmail.com> writes:
On Wednesday, 5 April 2017 at 11:39:47 UTC, Nicholas Wilson wrote:
 On Wednesday, 5 April 2017 at 09:31:09 UTC, harfel wrote:
 Dear all,

 [...]

 Following the documentation and code examples, I got the basic 
 functionality working. However, I am struggling with 
 implementing the magic functions __str__ and __hash__ of the 
 extension class. >> Is there a way to declare these slots in 
 PyD? I noticed that Repr does this for __repr__ and the 
 operator overloads do this of course for their respective 
 slots, but I could not find anything for __hash__ and __str__.

 [...]
I haven't chased the source but most likely __hash__ and __str__ will be "magically" generated from toHash() and toString() respectively (both methods of Object, see:https://dlang.org/phobos/object.html#.Object).
Unfortunately, this does not seem to be the case, as my D classes do override toHash and toString, but they are not called by the corresponding python classes.
Apr 05 2017