commit 45ebb3b798a9cf306ccfce512db8755e22cc472e
parent cd594065e953fe49c1ba109a1ceaf360f759a290
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Thu, 13 Jun 2024 21:43:46 +0200
Improve C++ interface with namespace
* Distintion between C and C++ interfaces
* Extract C++ interface from stamen.h into stamen.hpp
* Fix generation to reflect changes
Diffstat:
12 files changed, 105 insertions(+), 64 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stamen
- VERSION 1.0.0
+ VERSION 1.0.1
DESCRIPTION "Static menu generator"
LANGUAGES C CXX
)
diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt
@@ -9,12 +9,9 @@ add_custom_command(
COMMENT "Generating menu files"
)
-add_executable(demo
- main.cpp
- ${GENERATE_OUT}/demo_menu.cpp
-)
-
+add_executable(demo main.cpp ${GENERATE_OUT}/demo_menu.cpp)
target_link_libraries(demo stamen)
+set_target_properties(demo PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(demo PRIVATE ${GENERATE_OUT} ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(demo PROPERTIES
@@ -23,8 +20,6 @@ set_target_properties(demo PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${GENERATE_OUT}"
)
-
-
add_custom_command(
OUTPUT ${GENERATE_OUT}/demo_menu.h ${GENERATE_OUT}/demo_menu.c
COMMAND ${GENERATE_OUT}/stamen-generate ${GENERATE_OUT}/demo_menu.conf c
@@ -32,12 +27,9 @@ add_custom_command(
COMMENT "Generating cmenu files"
)
-add_executable(cdemo
- main.c
- ${GENERATE_OUT}/demo_menu.c
-)
-
+add_executable(cdemo main.c ${GENERATE_OUT}/demo_menu.c)
target_link_libraries(cdemo stamen)
+set_target_properties(cdemo PROPERTIES LINKER_LANGUAGE C)
target_include_directories(cdemo PRIVATE ${GENERATE_OUT} ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(cdemo PROPERTIES
diff --git a/demo/dynamic.cpp b/demo/dynamic.cpp
@@ -1,7 +1,9 @@
+#include "stamen.hpp"
#include <iostream>
-#include <stamen.h>
-const stamen::display_f stamen_display = stamen::builtin_display;
+// need to link against stamen library
+// in order to use stamen::builtin_display
+const stamen::display_f &stamen::display = stamen::builtin_display;
int finish(int) { exit(1); }
diff --git a/demo/main.cpp b/demo/main.cpp
@@ -4,8 +4,8 @@
#include <iostream>
// need to link against stamen library
-// in order to use stamen_builtin_display
-const stamen::display_f stamen_display = stamen::builtin_display;
+// in order to use stamen::builtin_display
+const stamen::display_f &stamen::display = stamen::builtin_display;
int operation1(int) {
std::cout << "operation 1" << std::endl;
diff --git a/include/menu.h b/include/menu.h
@@ -1,7 +1,7 @@
#ifndef STAMEN_MENU_H
#define STAMEN_MENU_H
-#include "stamen.h"
+#include "stamen.hpp"
#include <cstring>
#include <iostream>
diff --git a/include/stamen.h b/include/stamen.h
@@ -2,9 +2,8 @@
#define STAMEN_STAMEN_H
#ifdef __cplusplus
-#define EXTERNC extern "C"
-#else
-#define EXTERNC extern
+extern "C" {
+namespace stamen {
#endif
typedef int (*stamen_callback_f)(int);
@@ -18,25 +17,19 @@ struct stamen_item_t {
typedef int (*stamen_display_f)(const char *, const stamen_item_t[], int);
extern const stamen_display_f stamen_display;
-EXTERNC int stamen_dynamic(const char *code);
-EXTERNC void stamen_read(const char *filename);
-EXTERNC void stamen_insert(const char *code, stamen_callback_f callback);
-
-EXTERNC int stamen_builtin_display(const char *title,
- const stamen_item_t itemv[], int size);
-#ifdef __cplusplus
-namespace stamen {
+#if !defined __cplusplus || defined WITH_C_BINDINGS
-using callback_f = stamen_callback_f;
-using display_f = stamen_display_f;
-using item_t = stamen_item_t;
+int stamen_dynamic(const char *code);
+void stamen_read(const char *filename);
+void stamen_insert(const char *code, stamen_callback_f callback);
+int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
+ int size);
-const auto dynamic = stamen_dynamic;
-const auto read = stamen_read;
-const auto insert = stamen_insert;
-const auto builtin_display = stamen_builtin_display;
+#endif
+#ifdef __cplusplus
} // namespace stamen
+} // extern "C"
#endif
-#endif
+#endif // STAMEN_STAMEN_H
diff --git a/include/stamen.hpp b/include/stamen.hpp
@@ -0,0 +1,21 @@
+#ifndef STAMEN_STAMEN_HPP
+#define STAMEN_STAMEN_HPP
+
+#include "stamen.h"
+
+namespace stamen {
+
+using callback_f = stamen_callback_f;
+using display_f = stamen_display_f;
+using item_t = stamen_item_t;
+
+extern const display_f &display;
+
+int dynamic(const char *code);
+void read(const char *filename);
+void insert(const char *code, callback_f callback);
+int builtin_display(const char *title, const item_t itemv[], int size);
+
+} // namespace stamen
+
+#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -1,12 +1,15 @@
-add_library(stamen-include INTERFACE)
-target_include_directories(stamen-include INTERFACE ../include)
+add_library(stamen STATIC stamen.cpp menu.cpp c_bindings.cpp)
+target_include_directories(stamen PUBLIC ../include)
+target_compile_definitions(stamen PRIVATE WITH_C_BINDINGS)
+set_target_properties(stamen PROPERTIES LINKER_LANGUAGE CXX)
-add_library(stamen stamen.cpp menu.cpp)
-target_link_libraries(stamen PUBLIC stamen-include)
set_target_properties(stamen PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
- PUBLIC_HEADER ../include/stamen.h
+ DEBUG_POSTFIX "d"
+ PUBLIC_HEADER "../include/stamen.h;../include/stamen.hpp"
+ MACOSX_RPATH ON
+ WINDOWS_EXPORT_ALL_SYMBOLS ON
)
install(TARGETS stamen
diff --git a/src/c_bindings.cpp b/src/c_bindings.cpp
@@ -0,0 +1,19 @@
+#include "stamen.h"
+#include "stamen.hpp"
+
+namespace stamen {
+
+int stamen_dynamic(const char *code) { return dynamic(code); }
+
+void stamen_read(const char *filename) { return read(filename); }
+
+void stamen_insert(const char *code, stamen_callback_f callback) {
+ return insert(code, callback);
+}
+
+int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
+ int size) {
+ return builtin_display(title, itemv, size);
+}
+
+} // namespace stamen
diff --git a/src/generate.cpp b/src/generate.cpp
@@ -10,33 +10,44 @@ namespace stamen {
class Generator {
public:
- static void generateInclude(std::ostream &os) {
+ static void generateInclude(std::ostream &os, bool cpp) {
os << "#ifndef STAMEN_MENU_H\n";
os << "#define STAMEN_MENU_H\n\n";
- os << "#include <stamen.h>\n\n";
+
+ if (cpp) os << "#include \"stamen.hpp\"\n\n";
+ else os << "#include \"stamen.h\"\n\n";
+
for (const auto &[code, menu] : Menu::menu_lookup) {
os << std::format("int {}(int);\n", menu.getCode());
}
+
os << "\n#endif\n";
}
- static void generateSource(std::ostream &os) {
- os << "#include <stamen.h>\n";
+ static void generateSource(std::ostream &os, bool cpp) {
+ if (cpp) os << "#include \"stamen.hpp\"\n\n";
+ else os << "#include \"stamen.h\"\n\n";
+
os << "#include \"shared.h\"\n\n";
for (const auto &[code, menu] : Menu::menu_lookup) {
os << std::format("int {}(int) {{\n", menu.getCode());
- os << std::format("\tstatic const stamen_item_t items[] = {{\n");
+ if (cpp) os << "\tstatic const stamen::item_t items[] = ";
+ else os << "\tstatic const stamen_item_t items[] = ";
+
+ os << "{\n";
for (int i = 0; i < menu.getSize(); i++) {
- os << std::format("\t\t{{ {}, \"{}\" }},\n", menu.getCode(i),
- menu.getPrompt(i));
+ os << "\t\t{ " << menu.getCode(i);
+ os << ", \"" << menu.getPrompt(i) << "\" },\n";
}
- os << std::format("\t}};\n");
+ os << "\t};\n";
+
+ if (cpp) os << "\treturn stamen::display";
+ else os << "\treturn stamen_display";
- os << std::format("\treturn stamen_display(\"{}\", items, "
- "sizeof(items) / sizeof(items[0]));\n",
- menu.getTitle());
- os << std::format("}}\n\n");
+ os << std::format("(\"{}\"", menu.getTitle());
+ os << ", items, sizeof(items) / sizeof(items[0]));\n";
+ os << "}\n\n";
}
}
};
@@ -63,8 +74,8 @@ int main(const int argc, const char *argv[]) {
std::string ext = cpp ? "pp" : "";
std::ofstream source(base + ".c" + ext), include(base + ".h" + ext);
- Generator::generateSource(source);
- Generator::generateInclude(include);
+ Generator::generateSource(source, cpp);
+ Generator::generateInclude(include, cpp);
return 0;
}
diff --git a/src/menu.cpp b/src/menu.cpp
@@ -1,5 +1,4 @@
#include "menu.h"
-#include "stamen.h"
#include <deque>
#include <format>
diff --git a/src/stamen.cpp b/src/stamen.cpp
@@ -1,4 +1,4 @@
-#include "stamen.h"
+#include "stamen.hpp"
#include "menu.h"
#include <cmath>
@@ -7,16 +7,15 @@
#include <ostream>
#include <variant>
-using namespace stamen;
+namespace stamen {
-int stamen_dynamic(const char *code) { return Menu::dynamic(code); }
-void stamen_read(const char *filename) { Menu::read(filename); }
-void stamen_insert(const char *code, stamen_callback_f callback) {
+int dynamic(const char *code) { return Menu::dynamic(code); }
+void read(const char *filename) { Menu::read(filename); }
+void insert(const char *code, callback_f callback) {
Menu::insert(code, callback);
}
-int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
- int size) {
+int builtin_display(const char *title, const item_t itemv[], int size) {
const size_t digits = size_t(std::log10(size)) + 1;
const auto items = std::span(itemv, size_t(size));
int choice = 0;
@@ -56,3 +55,5 @@ int stamen_builtin_display(const char *title, const stamen_item_t itemv[],
return 1;
}
+
+} // namespace stamen