From 2de1893ebcb2626848e1b83d9487f4bf3ad8243f Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Tue, 20 Oct 2020 22:36:20 +0200
Subject: [PATCH] Provide simplified ad-hoc C++ wrapper for C-compiled libcerf

---
 Core/CMakeLists.txt                            |  9 +--------
 .../Computation/RoughMultiLayerComputation.cpp |  3 ++-
 ThirdParty/Core/cerf_wrapper/cerf              |  9 ---------
 ThirdParty/Core/cerf_wrapper/cerf_ptr.c        |  9 ---------
 ThirdParty/Core/cerf_wrapper/cerf_ptr.h        |  9 ---------
 ThirdParty/Core/cerfcpp.h                      | 18 ++++++++++++++++++
 cmake/BornAgain/Dependences.cmake              |  3 +++
 7 files changed, 24 insertions(+), 36 deletions(-)
 delete mode 100644 ThirdParty/Core/cerf_wrapper/cerf
 delete mode 100644 ThirdParty/Core/cerf_wrapper/cerf_ptr.c
 delete mode 100644 ThirdParty/Core/cerf_wrapper/cerf_ptr.h
 create mode 100644 ThirdParty/Core/cerfcpp.h

diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt
index 0c82a0cee4c..5ee89c23830 100644
--- a/Core/CMakeLists.txt
+++ b/Core/CMakeLists.txt
@@ -10,13 +10,6 @@ set(lib BornAgain${name})
 file(GLOB source_files */*.cpp)
 file(GLOB include_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} */*.h)
 
-if((NOT Cerf_IS_CPP) AND (NOT WIN32)) # TEMPORARY
-    list(APPEND source_files ${CMAKE_SOURCE_DIR}/ThirdParty/Core/cerf_wrapper/cerf_ptr.c)
-endif()
-if(${Cerf_IS_CPP})
-    string(APPEND CMAKE_CXX_FLAGS " -DCERF_AS_CPP=ON")
-endif()
-
 # --- make the library ---
 
 MakeLib(${name} ${lib} ${CMAKE_CURRENT_BINARY_DIR}/Wrap)
@@ -34,7 +27,7 @@ target_include_directories(${lib}
     PUBLIC ${CMAKE_SOURCE_DIR}
     ${tspectrum_INCLUDE_DIR}
     ${Cerf_INCLUDE_DIR}
-    ${CMAKE_SOURCE_DIR}/ThirdParty/Core/cerf_wrapper # TEMPORARY
+    ${CMAKE_SOURCE_DIR}/ThirdParty/Core/ # TEMPORARY
     )
 target_link_libraries(${lib}
     ${tspectrum_LIBRARY} ${Cerf_LIBRARIES})
diff --git a/Core/Computation/RoughMultiLayerComputation.cpp b/Core/Computation/RoughMultiLayerComputation.cpp
index 8677bafbd36..4b70e0b15f4 100644
--- a/Core/Computation/RoughMultiLayerComputation.cpp
+++ b/Core/Computation/RoughMultiLayerComputation.cpp
@@ -22,7 +22,8 @@
 #include "Sample/RT/ILayerRTCoefficients.h"
 #include "Sample/Slice/LayerInterface.h"
 #include "Sample/Slice/LayerRoughness.h"
-#include <cerf.h>
+
+#include "cerfcpp.h"
 
 // Diffuse scattering from rough interfaces is modelled after
 // Phys. Rev. B, vol. 51 (4), p. 2311 (1995)
diff --git a/ThirdParty/Core/cerf_wrapper/cerf b/ThirdParty/Core/cerf_wrapper/cerf
deleted file mode 100644
index ee3b0092612..00000000000
--- a/ThirdParty/Core/cerf_wrapper/cerf
+++ /dev/null
@@ -1,9 +0,0 @@
-// -*- mode: c++ -*-
-
-#include <cerf_ptr.h>
-
-std::complex<double> cerfcx(std::complex<double> z) {
-    std::complex<double> ret;
-    p_cerfcx((void*)&z, (void*)&ret);
-    return ret;
-}
diff --git a/ThirdParty/Core/cerf_wrapper/cerf_ptr.c b/ThirdParty/Core/cerf_wrapper/cerf_ptr.c
deleted file mode 100644
index 8754a0c1c64..00000000000
--- a/ThirdParty/Core/cerf_wrapper/cerf_ptr.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "cerf_ptr.h"
-#include "cerf.h"
-#include <string.h>
-
-void p_cerfcx(void* z, void* ret)
-{
-    double _Complex val = cerfcx(*(double _Complex*)(z));
-    memcpy(ret, &val, 2*sizeof(double));
-}
diff --git a/ThirdParty/Core/cerf_wrapper/cerf_ptr.h b/ThirdParty/Core/cerf_wrapper/cerf_ptr.h
deleted file mode 100644
index 00d565d6ab1..00000000000
--- a/ThirdParty/Core/cerf_wrapper/cerf_ptr.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void p_cerfcx(void* z, void* ret);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/ThirdParty/Core/cerfcpp.h b/ThirdParty/Core/cerfcpp.h
new file mode 100644
index 00000000000..29e7640e957
--- /dev/null
+++ b/ThirdParty/Core/cerfcpp.h
@@ -0,0 +1,18 @@
+/*
+This is an ad-hoc solution to make the C-compiled libcerf callable from C++ code.
+
+TODO:
+- Either, distribute this along with liberf.
+- Or, make sure the Debian, Homebrew etc packages distribute a libcerfcpp along with libcerf.
+
+*/
+
+#include <cerf.h>
+#include <complex>
+
+std::complex<double> cerfcx(const std::complex<double>& z)
+{
+    const _cerf_cmplx ret = cerfcx(*((_cerf_cmplx*)(&z)));
+    return {reinterpret_cast<const double(&)[2]>(ret)[0],
+            reinterpret_cast<const double(&)[2]>(ret)[1]};
+}
diff --git a/cmake/BornAgain/Dependences.cmake b/cmake/BornAgain/Dependences.cmake
index 8199d1c746c..6e790ff1b11 100644
--- a/cmake/BornAgain/Dependences.cmake
+++ b/cmake/BornAgain/Dependences.cmake
@@ -19,6 +19,9 @@ else()
 endif()
 
 find_package(Cerf REQUIRED)
+if(Cerf_IS_CPP)
+    add_compile_definitions(CERF_AS_CPP=ON)
+endif()
 
 # --- Boost ---
 set(Boost_NO_BOOST_CMAKE ON) # prevent shortcut
-- 
GitLab