Calling C++ library (CGAL) from Julia

#1

Hi,

What would be the best route for me to call the C++ library CGAL (https://www.cgal.org/) from Julia? Does anyone have experience calling this specific library? I know there are a few different packages to call C++ from Julia but I am not sure which is best? Suggestions of which packages to use for this would be great.

I would be nice if it worked across all platforms too, I saw that in the help of https://github.com/Keno/Cxx.jl only works on specific Linux distributions.

It also looks like there is a Python way of calling CGAL so I could get to this through PyCall? I would prefer calling C++ straight from Julia if possible.

Cheers,
Tim

0 Likes

#2

Hi,

CGAL is a very big library, what specific part(s) are you interested in? I would certainly recommend calling C++ directly, the parts they wrap in Python should also be easy to wrap using CxxWrap.jl or Cxx.jl.

Cheers,

Bart

1 Like

#3

Great, sounds good. I am interested in the Advancing front surface reconstruction algorithm (used it before in a package and its amazing) and some of the mesh simplification/resampling algorithms.

1 Like

#4

If you’re interested in a relatively small number of functions, you might want to consider writing a thin C wrapper around those functions (using extern "C" in your C/C++ code). This has the disadvantage of requiring some manual work, vut the benefit that calling a C shared library from Julia is extremely easy (using the built-in ccall) and works everywhere.

2 Likes

#5

did you read issue #390 and tried the solutions discussed in the comments? at least the binary-build solution should work fine on macOS and any Linux distributions that Julia is running on.

0 Likes

#6

I looked briefly at the interface for the Advancing front reconstruction, and I think it would be quite doable using CxxWrap and a custom C++ class to encapsulate the point set (e.g. adding iterators to a Julia array containing the points). Possibly a nicer way would be to store the points as an array of tuples or even fixed size arrays in Julia, but converting that without copying would take some adjustments in CxxWrap (which I am willing to do).

Either way, I think your final decision on how to wrap this will probably depend on how you want to store the input data on the Julia side.

0 Likes

#7

OK, thanks for the comments, it looks like I have a number of options. Currently my input data in Julia is just a 3*n array of the points (X,Y,Z) locations. e.g.

xyz=(Float64[1 1 0; 1 0 0;5 7 0;8 9 0;1 2 0])
5×3 Array{Float64,2}:
 1.0  1.0  0.0
 1.0  0.0  0.0
 5.0  7.0  0.0
 8.0  9.0  0.0
 1.0  2.0  0.0

To check i have understood, to use C++ wrap I now need to write a custom C++ class that defines these points?

0 Likes

#8

No, I mean a class that can wrap any array like that, for example:

class PointList
{
public:
  PointList(jlcxx::ArrayRef<double,2> points) : m_points(points) {}

  void print_points()
  {
    const std::size_t nb_points = m_points.size() / 3; // assuming 3D points
    for(std::size_t i = 0; i != nb_points; ++i)
    {
      std::cout << m_points[i] << ", " << m_points[i+nb_points] << ", " << m_points[i+2*nb_points] << std::endl;
    }
  }

private:
  jlcxx::ArrayRef<double,2> m_points;
};

In CxxWrap this is wrapped as:

  mod.add_type<PointList>("PointList")
    .constructor<ArrayRef<double,2>>()
    .method("print_points", &PointList::print_points);

And then used in Julia as:

xyz= Float64[1 1 0; 1 0 0;5 7 0;8 9 0;1 2 0]
pointlist = PointList(xyz)
print_points(pointlist)

Instead of the toy print_points function, the PointList class needs a C++ iterator function, so its begin and end iterator can be passed to the first two arguments of CGAL::advancing_front_surface_reconstruction. The advantage of this approach is that the points are not copied, the downside is that writing iterators in C++ is quite painful.

A simpler but more wasteful option would be to just copy the points from an ArrayRef to a std::vector<Point_3>.

1 Like