diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5155e2ce3780c55db19e9f16524bfd67b0f2e4a2..c4b99ebbf576293dbdd67d0adec828d2e47b07a7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,6 +13,7 @@ project(
 # scikit-build-core's built-in backport)
 find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
 find_package(pybind11 CONFIG REQUIRED)
+find_package(CGAL REQUIRED COMPONENTS ImageIO)
 
 # Add a library using FindPython's tooling (pybind11 also provides a helper like
 # this)
@@ -22,5 +23,10 @@ target_link_libraries(_core PRIVATE pybind11::headers)
 # This is passing in the version as a define just as an example
 target_compile_definitions(_core PRIVATE VERSION_INFO=${PROJECT_VERSION})
 
+python_add_library(_cgal MODULE src/cgal_example.cpp WITH_SOABI)
+target_link_libraries(_cgal PRIVATE pybind11::headers)
+target_link_libraries(_cgal PRIVATE CGAL::CGAL)
+
 # The install directory is the output (wheel) directory
 install(TARGETS _core DESTINATION pybind_example)
+install(TARGETS _cgal DESTINATION pybind_example)
diff --git a/pyproject.toml b/pyproject.toml
index e5d7fd4e666d0355bd197231c7132a0f9016ecec..d32dfa001876704c70defcf51cf77f01a4d93e29 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -29,6 +29,8 @@ test = ["pytest"]
 
 
 [tool.scikit-build]
+cmake.verbose = true
+logging.level = "INFO"
 wheel.expand-macos-universal-tags = true
 
 
diff --git a/src/cgal_example.cpp b/src/cgal_example.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7ef74d353a13baf084afc4d80bf813950720d044
--- /dev/null
+++ b/src/cgal_example.cpp
@@ -0,0 +1,77 @@
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+
+#include <CGAL/Mesh_triangulation_3.h>
+#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
+#include <CGAL/Mesh_criteria_3.h>
+
+#include <CGAL/Labeled_image_mesh_domain_3.h>
+#include <CGAL/make_mesh_3.h>
+#include <CGAL/Image_3.h>
+
+#include <CGAL/ImageIO.h>
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h> // This header is needed to work with STL containers like std::vector
+
+// Domain
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+typedef CGAL::Labeled_mesh_domain_3<K> Mesh_domain;
+
+// Triangulation
+typedef CGAL::Mesh_triangulation_3<Mesh_domain, CGAL::Default, CGAL::Sequential_tag>::type Tr;
+typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
+
+// Criteria
+typedef CGAL::Mesh_criteria_3<Tr> Mesh_criteria;
+
+
+int cgalMesh3DImage(const std::string& image_filename, const std::string& mesh_filename)
+{
+    CGAL::Image_3 image;
+    if(!image.read(image_filename)){
+        std::cerr << "Error: Cannot read file " <<  image_filename << std::endl;
+        return EXIT_FAILURE;
+    }
+    Mesh_domain domain = Mesh_domain::create_labeled_image_mesh_domain(image);
+
+    // Mesh criteria
+    auto params = CGAL::parameters::facet_angle(30);
+    params.facet_size(6);
+    params.facet_distance(4);
+    params.cell_radius_edge_ratio(3);
+    params.cell_size(8);
+    Mesh_criteria criteria(params);
+
+    C3t3 c3t3 = CGAL::make_mesh_3<C3t3>(domain, criteria);
+
+    // Output
+    std::ofstream medit_file(mesh_filename);
+    CGAL::IO::write_MEDIT(medit_file, c3t3);
+    medit_file.close();
+    return 0;
+}
+
+
+namespace py = pybind11;
+
+PYBIND11_MODULE(_cgal, m) {
+    m.doc() = R"pbdoc(
+        CGAL example function
+        ---------------------
+
+        .. currentmodule:: pybind_example.cgal
+
+        .. autosummary::
+           :toctree: _generate
+
+           add
+           subtract
+    )pbdoc";
+
+    m.def("mesh_3d_image", &cgalMesh3DImage, R"pbdoc(
+        Domains From Segmented 3D Images
+
+        The function produces a 3D mesh from a 3D image.
+    )pbdoc", py::arg("image_filename"), py::arg("mesh_filename"));
+
+}
diff --git a/src/pybind_example/cgal.py b/src/pybind_example/cgal.py
new file mode 100644
index 0000000000000000000000000000000000000000..c75eae244710b9ec3c2c838992c3c4104bebf921
--- /dev/null
+++ b/src/pybind_example/cgal.py
@@ -0,0 +1,8 @@
+from __future__ import annotations
+
+from ._cgal import __doc__, mesh_3d_image
+
+__all__ = [
+    "__doc__",
+    "mesh_3d_image"
+]
diff --git a/tests/test_cgal.py b/tests/test_cgal.py
new file mode 100644
index 0000000000000000000000000000000000000000..95372164deb10987e1a5cd7d72e0bb497ab5590b
--- /dev/null
+++ b/tests/test_cgal.py
@@ -0,0 +1,23 @@
+import unittest
+import tempfile
+import os
+
+from pybind_example.cgal import mesh_3d_image
+
+
+class TestCgalMesh(unittest.TestCase):
+
+    def setUp(self):
+        self.image_filename = tempfile.mktemp(suffix=".inr.gz")
+        self.mesh_filename = tempfile.mktemp(suffix=".medit")
+
+    def tearDown(self):
+        if os.path.exists(self.image_filename):
+            os.remove(self.image_filename)
+        if os.path.exists(self.mesh_filename):
+            os.remove(self.mesh_filename)
+
+    def test_tissue_image_surface_topomesh(self):
+        res = mesh_3d_image(self.image_filename, self.mesh_filename)
+        assert res == 1 # should not work for now, test that it fails
+        assert not os.path.exists(self.mesh_filename)