diff --git a/cpp/ska-sdp-func-bindings/CMakeLists.txt b/cpp/ska-sdp-func-bindings/CMakeLists.txt
index 278cc6a403bcd4d98a77c9cd466a3ffc9967df7e..f2b100c787e5dc345cef194724abd39bcc4479b7 100644
--- a/cpp/ska-sdp-func-bindings/CMakeLists.txt
+++ b/cpp/ska-sdp-func-bindings/CMakeLists.txt
@@ -1,7 +1,7 @@
 # Copyright (C) 2023 ASTRON (Netherlands Institute for Radio Astronomy)
 # SPDX-License-Identifier: GPL-3.0-or-later
 
-add_library(ska-sdp-func-everybeam OBJECT skasdpfunceverybeam.cc
+add_library(ska-sdp-func-everybeam OBJECT sdp_element.cc skasdpfunceverybeam.cc
                                           skasdpfuncelementresponse.cc)
 
 # The ska-sdp-func-everybeam object library is included in the SHARED library everybeam
@@ -11,7 +11,8 @@ set_property(TARGET ska-sdp-func-everybeam PROPERTY POSITION_INDEPENDENT_CODE
 
 target_link_libraries(ska-sdp-func-everybeam ska-sdp-func::ska-sdp-func xtensor)
 
-install(FILES skasdpfunceverybeam.h DESTINATION "include/${CMAKE_PROJECT_NAME}")
+install(FILES skasdpfunceverybeam.h sdp_element.h
+        DESTINATION "include/${CMAKE_PROJECT_NAME}")
 
 add_executable(tbindings tbindings.cc)
 target_link_libraries(tbindings everybeam ska-sdp-func::ska-sdp-func)
diff --git a/cpp/ska-sdp-func-bindings/sdp_element.cc b/cpp/ska-sdp-func-bindings/sdp_element.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ad53898c1788a677b9e2dfd4c25cab90970e29fb
--- /dev/null
+++ b/cpp/ska-sdp-func-bindings/sdp_element.cc
@@ -0,0 +1,41 @@
+#include "sdp_element.h"
+
+#include <map>
+#include <string>
+
+namespace {
+std::map<std::string,
+         std::tuple<make_function_t, destroy_function_t, evaluate_function_t>>&
+get_sdp_element_function_map() {
+  static std::map<std::string, std::tuple<make_function_t, destroy_function_t,
+                                          evaluate_function_t>>
+      function_map;
+  return function_map;
+}
+}  // namespace
+
+int sdp_register_element(const char* name, const make_function_t make_function,
+                         const destroy_function_t destroy_function,
+                         const evaluate_function_t evaluate_function) {
+  std::map<std::string, std::tuple<make_function_t, destroy_function_t,
+                                   evaluate_function_t>>& function_map =
+      get_sdp_element_function_map();
+  function_map[name] =
+      std::make_tuple(make_function, destroy_function, evaluate_function);
+  return 0;
+}
+
+sdp_Error sdp_get_element_functions(const char* name,
+                                    make_function_t& make_function,
+                                    destroy_function_t& destroy_function,
+                                    evaluate_function_t& evaluate_function) {
+  std::map<std::string, std::tuple<make_function_t, destroy_function_t,
+                                   evaluate_function_t>>& function_map =
+      get_sdp_element_function_map();
+
+  if (!function_map.count(name)) return SDP_ERR_INVALID_ARGUMENT;
+
+  std::tie(make_function, destroy_function, evaluate_function) =
+      function_map[name];
+  return SDP_SUCCESS;
+}
diff --git a/cpp/ska-sdp-func-bindings/sdp_element.h b/cpp/ska-sdp-func-bindings/sdp_element.h
new file mode 100644
index 0000000000000000000000000000000000000000..74111c44dcf48994418668f0b2fa3e6739a95016
--- /dev/null
+++ b/cpp/ska-sdp-func-bindings/sdp_element.h
@@ -0,0 +1,30 @@
+#include <ska-sdp-func/utility/sdp_errors.h>
+#include <ska-sdp-func/utility/sdp_mem.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* sdp_element_t;
+
+typedef sdp_element_t (*make_function_t)(const char* name);
+
+typedef void (*destroy_function_t)(sdp_element_t element_response);
+
+typedef void (*evaluate_function_t)(sdp_element_t element_response,
+                                    int num_points, const sdp_Mem* theta,
+                                    const sdp_Mem* phi, sdp_Mem* response);
+
+[[gnu::visibility("default")]] int sdp_register_element(
+    const char* name, const make_function_t make_function,
+    const destroy_function_t destroy_function,
+    const evaluate_function_t evaluate_function);
+
+[[gnu::visibility("default")]] sdp_Error sdp_get_element_functions(
+    const char* name, make_function_t& make_function,
+    destroy_function_t& destroy_function,
+    evaluate_function_t& evaluate_function);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cpp/ska-sdp-func-bindings/skasdpfuncelementresponse.h b/cpp/ska-sdp-func-bindings/skasdpfuncelementresponse.h
index a87ede239aba5d00ae80096176a9c72b1db14825..d20f4f018a0630efda2f1e6df8d8ac36c984d443 100644
--- a/cpp/ska-sdp-func-bindings/skasdpfuncelementresponse.h
+++ b/cpp/ska-sdp-func-bindings/skasdpfuncelementresponse.h
@@ -8,7 +8,7 @@
 
 #include <memory>
 
-#include <ska-sdp-func/station_beam/sdp_element.h>
+#include "sdp_element.h"
 
 namespace everybeam {
 
diff --git a/cpp/ska-sdp-func-bindings/skasdpfunceverybeam.h b/cpp/ska-sdp-func-bindings/skasdpfunceverybeam.h
index 931b792393024930e36ca76c12206f5145370d16..630bc12406f51ce9adfdb4873a9af8510a030426 100644
--- a/cpp/ska-sdp-func-bindings/skasdpfunceverybeam.h
+++ b/cpp/ska-sdp-func-bindings/skasdpfunceverybeam.h
@@ -1,4 +1,4 @@
-#include <ska-sdp-func/station_beam/sdp_element.h>
+#include "sdp_element.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/cpp/ska-sdp-func-bindings/tbindings.cc b/cpp/ska-sdp-func-bindings/tbindings.cc
index 0452a2d3cbee9c7082c9e17939cc11e0063ed873..9413e9a6c4f96d1ea1c6e835a1c62475cfea84e2 100644
--- a/cpp/ska-sdp-func-bindings/tbindings.cc
+++ b/cpp/ska-sdp-func-bindings/tbindings.cc
@@ -1,4 +1,4 @@
-#include "ska-sdp-func/station_beam/sdp_element.h"
+#include "sdp_element.h"
 
 #include <complex>
 #include <dlfcn.h>