On Thu, Feb 6, 2014 at 1:53 PM, Gary Oberbrunner <ga...@genarts.com> wrote: > I have a function returning a bp::list, so: > > static bp::list EXTget_params(Container *g) > { > bp::list param_list; > int n_params = g->n_params; > for (int i = 0; i < n_params; i++) { > // Need this boost::ref to put a ref to the param into the list > // rather than a param itself. (That would cause it to try to copy the > // param, but it's listed as noncopyable so it would just get a > TypeError.) > param_list.append(bp::ref(g->params[i])); > } > return param_list; > } > > Note that the Param is noncopyable. Its lifetime is managed by Container. > The above works, except each time it runs it makes new bp::ref objects, which > don't compare equal to each other: > > param1 = g.get_params()[0] > param2 = g.get_params()[0] // should be same as param1 > if param1 == param2: > print "Success!" > > It doesn't print success, because the bp::ref objects are different, and > don't have operator== to compare their referents (at least that's my guess > about what's going on). Is there something else I can use instead of bp::ref > here that will cause the list items to "point to" the same param each time I > call get_params()? >
bp::ref isn't actually a kind of object; it's just a hint to Boost.Python that it shouldn't deep-copy your object when converting it to Python. The problem is simply that because you don't have a Python __eq__ operator defined, you're comparing the pointers of the Python objects that hold your C++ objects (mostly what you'd guessed). And when you create a new Python object from a C++ object in general, there's no easy way for Boost.Python to get at some previously-Python-ized instance of that same object so it can just return the same Python object again. I think there are two ways to address this: - You can wrap the things you're putting in the list in such a way that Boost.Python has them hold a pointer to their own Python selves. Then, when they're converted back to Python, I believe Boost.Python will just use that internal pointer. But this will only work if all the things in the list were originally constructed by calling their constructors in Python (otherwise those internal pointers can't get initialized), and I'm not positive it will all work even then. There's more information on how to do that here: http://www.boost.org/doc/libs/1_53_0/libs/python/doc/v2/class.html#HeldType - Add a __eq__/__ne__ overrides to the class of things you're putting in the list, with an implementation that compares C++ pointers, not Python pointers. This is almost certainly much easier, but it's a little less "complete" as a solution, in the sense that you'll still be getting different Python objects back for the same C++ object (so while "param2 == param1" will succeed, "param1 is param2" will still fail). Good luck! Jim _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org https://mail.python.org/mailman/listinfo/cplusplus-sig