PYBIND11:当python解释器嵌入并在另一个线程中运行时,对另一个c++线程中的类对象值进行更改



我只是在python中打印car1.vehicle_id的值。我想把它打印成";1234";在前2秒,然后当值在另一个线程中变为"0"时;4543〃;更改应该在python中生效。这可能吗?或者有一个简单的例子可以帮助我吗?

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)

电流输出

总是1234

所需输出

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

您需要了解用于线程的C++规则。在C++中,线程在并行环境中的运行效果比在Python中要好得多。这是因为在C++中,线程默认情况下是完全独立运行的,而Python使用全局解释器锁,这会导致大量线程同步。

因此,在这种情况下,您确实需要同步线程,因为线程共享一个变量(car1(。挑战在于.def_readonly隐藏了一些不进行同步的样板代码——这是有道理的,因为它应该使用什么对象进行同步?

因此,您需要做的是在Vehicle中创建getter和setter方法,并添加一个std::mutex。在每个getter和setter中,都可以锁定和解锁这个互斥对象。这对于std::scoped_lock来说很容易——当方法返回时,这将自动解锁互斥对象。

还有其他选择。对于vehicle_id,可以使用std::atomic_int,但可能仍然需要getter方法。我不认为pybind理解原子变量。

最新更新