Skip to content

Commit

Permalink
[API] changes for Julia bindings (#1016)
Browse files Browse the repository at this point in the history
This PR brings some changes to the API, in order to facilitate the creation of Julia bindings for SIRIUS in a future SIRIUS.jl package.

Apart from the additions of new functions to sirius_api.cpp (necessary for the DFTK integration), the main addition consists of a header file for the API: sirius_c_headers.h. It turns out that having a header file drastically simplifies the process of creating Julia bindings for a C/C++ library.

As things stand, this header file is generated by a script (generate_c_headers.py), in the same spirit as the Fortran API. As a result, it is not used for compilation, but only as source material for the automatic generation of Julia bindings.
  • Loading branch information
abussy authored Aug 20, 2024
1 parent 248e1b3 commit 14bf6e0
Show file tree
Hide file tree
Showing 5 changed files with 4,479 additions and 102 deletions.
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ if(SIRIUS_CREATE_FORTRAN_BINDINGS)
set_target_properties(sirius PROPERTIES Fortran_MODULE_DIRECTORY mod_files)
install(FILES "${PROJECT_BINARY_DIR}/src/mod_files/sirius.mod"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/sirius")
install(FILES "${PROJECT_SOURCE_DIR}/src/api/sirius_c_headers.h"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/sirius/src/api")
install(TARGETS sirius
EXPORT sirius_targets
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
Expand Down
48 changes: 48 additions & 0 deletions src/api/generate_c_headers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# This script generates a basic header file from the sirius_api.cpp file
# A lot of assumptions are made: all functions are void, we only care about the extern "C",
# etc. In the end, the idea is to provide an input for Clang.jl wrapping

import re
import sys

#Only read the file from the extern "C" section beginning
is_extern = False
content = ""
with open("sirius_api.cpp", "r") as myfile:
for line in myfile:
if not is_extern:
if line.startswith("extern"):
is_extern = True

if is_extern:
content += line

#We want C-style complex types, not C++
content = content.replace("std::complex<double>", "double complex")

#A regex that matches all SIRIUS API calls: returns a void,
#starts with sirius_, and allows for line breaks
pattern = r'\bvoid\s+(?:\s*\n\s*)?sirius_\w+\s*\([^{]*\{'
matches = re.findall(pattern, content, re.DOTALL)

signatures = []
for match in matches:
signatures.append(match.strip().replace("\n{", ";\n\n"))

#We also want to carry over the Fortran API info
pattern = r'@api begin(.*?)@api end'
matches = re.findall(pattern, content, re.DOTALL)
docs = []
for match in matches:
docs.append("/*\n"+match.strip()+"\n*/\n")

with open("sirius_c_headers.h", "w") as myfile:
myfile.write("#include <stdbool.h>\n")
myfile.write("#include <complex.h>\n\n")
for doc in docs:
fname = doc.split("\n")[1][:-1]
for signature in signatures:
if fname+"(" in signature:
myfile.write(doc)
myfile.write(signature)
break
Loading

0 comments on commit 14bf6e0

Please sign in to comment.