It took me some time to figure out the issues like 
	"ImportError: generic_type: type "VertexProperty_easy3d_PolyMesh_VertexConnectivity_t" referenced unknown base type "easy3d::Property<easy3d::PolyMesh::VertexConnectivity>"

It seems in the bindings code, the order of the definition of the types matters. The solution is quite straight forward.
You will see 
	struct PyCallBack_easy3d_Property_easy3d_PolyMesh_VertexConnectivity_t : public easy3d::Property<easy3d::PolyMesh::VertexConnectivity> { ... }
and 
	pybind11::class_<easy3d::Property<easy3d::PolyMesh::VertexConnectivity>, std::shared_ptr<easy3d::Property<easy3d::PolyMesh::VertexConnectivity>>, PyCallBack_easy3d_Property_easy3d_PolyMesh_VertexConnectivity_t> cl(m, "Property_easy3d_PolyMesh_VertexConnectivity_t", "");

Just put the definition of 
	"Property_easy3d_PolyMesh_VertexConnectivity_t"
before
 	"VertexProperty_easy3d_PolyMesh_VertexConnectivity_t"

The error occurs because pybind11 requires that a base class (easy3d::Model) is registered before a derived class (easy3d::Graph).
If the derived class is registered before the base class, it results in the "unknown base type" error.





Issues with C++ reference as argument.
In C++, your function signature modifies the squared_distance argument directly because it is passed by reference (float &).
However, Python doesn’t have the concept of pass-by-reference in the same way. In Pybind11, you must explicitly wrap such arguments to achieve the desired behavior.

        cl.def("find_closest_point",
               [](const easy3d::KdTreeSearch_ANN &self, const easy3d::vec3 &p) {
                   return self.find_closest_point(p);
               },
               "Queries the closest point for a given point (without returning squared distance)",
               pybind11::arg("p"));

        cl.def("find_closest_point_with_squared_distance",
               [](const easy3d::KdTreeSearch_ANN &self, const easy3d::vec3 &p) {
                   float squared_distance = 0.0f;
                   int result = self.find_closest_point(p, squared_distance);
                   return std::make_pair(result, squared_distance);
               },
               "Queries the closest point for a given point (returns squared distance as well)",
               pybind11::arg("p"));

Instead of exposing the original find_closest_point directly, a lambda function is used as a wrapper. Inside this wrapper:
A temporary variable squared_distance is created to store the output.
The original find_closest_point function is called, modifying squared_distance.
The result is returned as a std::pair<int, float>.
In Python, you can now return both the result (the closest point ID) and the squared distance in a tuple, like this:
	point = [1.0, 2.0, 3.0]  
	kdtree = easy3d.KdTreeSearch_ANN(pc)
	id = kdtree.find_closest_point(point)
	id, sd = kdtree.find_closest_point_with_squared_distance(point)