简体   繁体   中英

PYBIND11: Make changes to class object value in another c++ thread when python interpreter is embedded and running in another thread

I am just printing the value of car1.vehicle_id in python. I want it to print "1234" for the first 2 seconds and then when the value is changes in another thread to " 4543" the change should take effect in python. Is this possible or is there a simple example to help me with this?

c++

 #include <pybind11/embed.h> #include <string> #include <thread> #include <chrono> // Define namespace for pybind11 namespace py = pybind11; class Vehiclee { // Access specifier public: Vehiclee(){}; ~Vehiclee() {} // Data Members int vehicle_id; std::string vehicle_name; std::string vehicle_color; // Member Functions() void printname() { std::cout << "Vehicle id is: " << vehicle_id; std::cout << "Vehicle name is: " << vehicle_name; std::cout << "Vehicle color is: " << vehicle_color; } }; PYBIND11_EMBEDDED_MODULE(embeded, m){ py::class_(m, "Vehiclee").def_readonly("vehicle_name", &Vehiclee::vehicle_name).def_readonly("vehicle_color", &Vehiclee::vehicle_color).def_readonly("vehicle_id", &Vehiclee::vehicle_id); } py::scoped_interpreter python{}; Vehiclee car1; void threadFunc() { sleep(2); std::cout<<"entering thread"; car1.vehicle_id = 4543; std::cout<<"Modified val in thread"; } int main() { // Initialize the python interpreter // Import all the functions from scripts by file name in the working directory auto simpleFuncs = py::module::import("simpleFuncs"); // Test if C++ objects can be passed into python functions car1.vehicle_id = 1234; std::thread t1(threadFunc); simpleFuncs.attr("simplePrint")(car1); t1.join(); return 0; }

python

>  import time 
>  import importlib 
>  import embeded
>      
>     def simplePrint(argument): 
>           while(1): 
>               importlib.reload(embeded)
>               print(argument.vehicle_id) time.sleep(1)

Current output

always 1234

Required output

1234 (for first 2 secs)
4543 (after 2 secs)

You need to understand the C++ rules for threading. In C++, threads can run far better in parallel than in Python. This is because in C++, threads are by default running entirely separate from each other, whereas Python uses a Global Interpreter Lock which causes a lot of thread synchronization.

So, in this case you do need the threads to synchronize, because the threads share a variable ( car1 ). The challenge is that .def_readonly hides some boilerplate code which doesn't do synchronization - makes sense, because what object should it use to synchronize?

So what you need to do is make getter and setter methods in Vehicle , and add a std::mutex . In every getter and every setter, you lock and unlock this mutex. This is easy with a std::scoped_lock - this will automatically unlock the mutex when the method returns.

There are other options. For vehicle_id you could use a std::atomic_int , but you'd probably still need a getter method. I don't think pybind understands atomic variables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM