Skip to content

c++ function that modifies reference not reflected in python #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mlund opened this issue Nov 27, 2015 · 9 comments
Closed

c++ function that modifies reference not reflected in python #16

mlund opened this issue Nov 27, 2015 · 9 comments

Comments

@mlund
Copy link

mlund commented Nov 27, 2015

Hi Jakob,
In C++ I have a class Space with public member vector<PointParticle> p and a non-class function template,

template<class Tspace>
   void cm2origo(Tspace::Tparticlevector &p) { /* modify p */ }

Wrapping is done with,

typedef Space<PointParticle> Tspace;

m.def("cm2origo",  &cm2origo<Tspace>);

py::class_<Tspace>(m, "Space")
  .def_readwrite("p", &Tspace::p)
  .def ... 

In python I can read/write to p as one would expect. However, when calling the exposed cm2origo function, changes to p are not transferred back to python. Any suggestions how to sort this out?

@wjakob
Copy link
Member

wjakob commented Nov 27, 2015

The STL auto-binding code in stl.h transparently converts a std::vector to a Python list, but it does not transfer back changes (this is intentional, it would be costly to have to do a full sweep over the vector after each function call to detect changes and re-synchronize).

You will have to create your own bindings for a custom std::vector that "stays" on the C++ side, and which can be accessed from Python using iterators and the slicing protocol. See example 6 of the included demo plugin.

@wjakob wjakob closed this as completed Nov 27, 2015
@mlund
Copy link
Author

mlund commented Nov 27, 2015

Thanks. I'd rather not change the c++ side and tried to define my vector as:

py::class_<Tspace::particlevector> _pvec(m, "particlevector");
 _pvec.def("__len__", &Tspace::particlevector::size);

hoping that Space.p would be returned as python type particlevector but it's still list. Any way to override the automatic STL conversion other than removing the header which is otherwise needed? I understand the performance issue mentioned in your last post, but wonder if it's possible to copy only for the case where the list is passed as a non-const argument. It certainly seems more intuitive, safe.

@wjakob
Copy link
Member

wjakob commented Nov 27, 2015

Can't you just avoid including <pybind11/stl.h>? In that case, your custom type definition will have precedence.

@wjakob
Copy link
Member

wjakob commented Nov 27, 2015

(other than that, your class definition looks good)

@mlund
Copy link
Author

mlund commented Nov 27, 2015

Sure, but then all stl return types need to be manually specialized to get pythonic behavior, right? The project is rather large so slightly more fine-grained control of the implicit stl conversion would probably be useful, perhaps as an option ala the return policies. Thanks / Mikael

@wjakob
Copy link
Member

wjakob commented Nov 27, 2015

It's tricky due to do this since the type casting system relies on template partial overloads that can't just be turned off once they have been introduced. I'm all ears if you have an idea, but I hesitate to complicate the library for this use case.

@mlund
Copy link
Author

mlund commented Nov 28, 2015

I can surely imagine it's non-trivial; I'll post my solution/workaround here when done. Thanks / Mikael

EricCousineau-TRI referenced this issue in EricCousineau-TRI/pybind11 Apr 24, 2018
eigen: Fix dtype=object shape conversion for 1D NumPy arrays for Eigen matrices
@levinandrew
Copy link

@mlund were you able to find a solution to this issue?

@vagrawal-aptina
Copy link

hi, did you get the solution/workaround for this problem?
I am facing a very similar problem in my code.
Any help will be highly appreciated.
Thanks, Vishal

sschnug pushed a commit to sschnug/pybind11 that referenced this issue Aug 2, 2024
When building additional, auxiliary libraries they should receive
proper handling in "native_libs.txt". Surprisingly, this only
happens when a trailing `/` is added.

Also, the primary module will then go into the package directory.

Additional `RPATH`/`RUNPATH` handling for auxiliary, "native" libs
is likely needed. E.g. on Linux/OSX:

```
            '-DCMAKE_INSTALL_RPATH=$ORIGIN',
            '-DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON',
            '-DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=OFF',
```

while on Windows one can just keep a flat structure in the package,
which will be in `%PATH%`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants