Skip to content

Commit b36c04e

Browse files
authored
Merge pull request #684 from triuk/main
add class-based call_js_from_cpp example and member-function bind overload
2 parents 22598d2 + 98b2c66 commit b36c04e

File tree

6 files changed

+390
-9
lines changed

6 files changed

+390
-9
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,18 @@ if (WEBUI_BUILD_EXAMPLES)
122122

123123
add_executable(minimal ${CMAKE_CURRENT_SOURCE_DIR}/examples/C++/minimal/main.cpp)
124124
add_executable(call_js_from_cpp ${CMAKE_CURRENT_SOURCE_DIR}/examples/C++/call_js_from_cpp/main.cpp)
125+
add_executable(call_js_from_cpp_class ${CMAKE_CURRENT_SOURCE_DIR}/examples/C++/call_js_from_cpp_class/main.cpp)
125126
add_executable(call_js_from_c ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/call_js_from_c/main.c)
126127

127128
target_link_libraries(minimal webui)
128129
target_link_libraries(call_js_from_cpp webui)
130+
target_link_libraries(call_js_from_cpp_class webui)
129131
target_link_libraries(call_js_from_c webui)
130132

131133
if (MSVC)
132134
set_target_properties(minimal PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
133135
set_target_properties(call_js_from_cpp PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
136+
set_target_properties(call_js_from_cpp_class PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
134137
set_target_properties(call_js_from_c PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
135138
endif()
136139

examples/C++/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The only requirement to build the examples is a a C++11 compiler.
77
- `minimal`: Creates a minimal WebUI application.
88
- `call_c_from_js`: Calls C++ from JavaScript.
99
- `call_js_from_c`: Calls JavaScript from C++.
10+
- `call_js_from_cpp_class`: Calls JavaScript from C++ using class methods and member-function bind.
1011
- `serve_a_folder`: Uses WebUI to serve a folder that contains multiple files.
1112

1213
To build an example, cd into its directory and run the make command.
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# WebUI C++ Example
2+
3+
# == 1. VARIABLES =============================================================
4+
5+
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
6+
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
7+
TARGET := $(firstword $(MAKECMDGOALS))
8+
LIB_DIR := $(PROJECT_DIR)/dist
9+
ifeq ($(TARGET), debug)
10+
LIB_DIR := $(LIB_DIR)/debug
11+
endif
12+
INCLUDE_DIR := $(PROJECT_DIR)/include
13+
WEBUI_LIB_NAME = webui-2
14+
ifeq ($(WEBUI_USE_TLS), 1)
15+
WEBUI_LIB_NAME = webui-2-secure
16+
endif
17+
18+
# ARGS
19+
# Set a compiler when running on Linux via `make CC=g++` / `make CC=clang`
20+
CC = g++
21+
# Build the WebUI library if running via `make BUILD_LIB=true`
22+
BUILD_LIB ?=
23+
24+
# BUILD FLAGS
25+
STATIC_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
26+
DYN_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
27+
28+
# Platform conditions
29+
ifeq ($(OS),Windows_NT)
30+
# Windows
31+
PLATFORM := windows
32+
SHELL := CMD
33+
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -lstdc++ -luuid -static
34+
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
35+
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32 -lstdc++ -luuid
36+
STATIC_OUT := main.exe
37+
DYN_OUT := main-dyn.exe
38+
LWS2_OPT := -lws2_32 -lole32
39+
STRIP_OPT := --strip-all
40+
CONSOLE_APP := -Wl,-subsystem=console
41+
GUI_APP := -Wl,-subsystem=windows
42+
else
43+
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lpthread -lm -ldl
44+
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME) -lpthread -lm -ldl
45+
STATIC_OUT := main
46+
DYN_OUT := main-dyn
47+
ifeq ($(shell uname),Darwin)
48+
# MacOS
49+
PLATFORM := macos
50+
CC = clang
51+
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
52+
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
53+
else
54+
# Linux
55+
PLATFORM := linux
56+
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
57+
STRIP_OPT := --strip-all
58+
ifeq ($(CC),clang)
59+
LLVM_OPT := llvm-
60+
endif
61+
endif
62+
endif
63+
64+
# == 2.TARGETS ================================================================
65+
66+
all: release
67+
68+
debug: --validate-args
69+
ifeq ($(BUILD_LIB),true)
70+
@cd "$(PROJECT_DIR)" && $(MAKE) debug
71+
endif
72+
# Static with Debug info
73+
ifneq ($(WEBUI_USE_TLS), 1)
74+
@echo "Build C++ Example ($(CC) debug static)..."
75+
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
76+
endif
77+
# Dynamic with Debug info
78+
@echo "Build C++ Example ($(CC) debug dynamic)..."
79+
$(COPY_LIB_CMD)
80+
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
81+
# Clean
82+
ifeq ($(PLATFORM),windows)
83+
@- del *.o >nul 2>&1
84+
else
85+
@- rm -f *.o
86+
@- rm -rf *.dSYM # macOS
87+
endif
88+
@echo "Done."
89+
90+
release: --validate-args
91+
ifeq ($(BUILD_LIB),true)
92+
@cd "$(PROJECT_DIR)" && $(MAKE)
93+
endif
94+
# Static Release
95+
ifneq ($(WEBUI_USE_TLS), 1)
96+
@echo "Build C++ Example ($(CC) release static)..."
97+
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
98+
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
99+
endif
100+
# Dynamic Release
101+
@echo "Build C++ Example ($(CC) release dynamic)..."
102+
$(COPY_LIB_CMD)
103+
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
104+
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
105+
# Clean
106+
ifeq ($(PLATFORM),windows)
107+
@- del *.o >nul 2>&1
108+
else
109+
@- rm -f *.o
110+
@- rm -rf *.dSYM # macOS
111+
endif
112+
@echo "Done."
113+
114+
clean: --clean-$(PLATFORM)
115+
116+
# INTERNAL TARGETS
117+
118+
--validate-args:
119+
ifneq ($(filter $(CC),g++ clang aarch64-linux-gnu-g++ arm-linux-gnueabihf-g++ musl-g++),$(CC))
120+
$(error Invalid compiler specified: `$(CC)`)
121+
endif
122+
123+
--clean-linux: --clean-unix
124+
125+
--clean-macos: --clean-unix
126+
127+
--clean-unix:
128+
- rm -f *.o
129+
- rm -f *.a
130+
- rm -f *.so
131+
- rm -f *.dylib
132+
- rm -rf *.dSYM
133+
134+
--clean-windows:
135+
- del *.o >nul 2>&1
136+
- del *.dll >nul 2>&1
137+
- del *.a >nul 2>&1
138+
- del *.exe >nul 2>&1
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# WebUI C++ Example
2+
# Windows - Microsoft Visual C++
3+
4+
SHELL = CMD
5+
LIB_DIR = ../../../dist
6+
INCLUDE_DIR = ../../../include
7+
WEBUI_LIB_NAME = webui-2
8+
!IF "$(WEBUI_USE_TLS)" == "1"
9+
WEBUI_LIB_NAME = webui-2-secure
10+
!ENDIF
11+
12+
# Build the WebUI library if running `nmake BUILD_LIB=true`
13+
BUILD_LIB =
14+
15+
all: release
16+
17+
debug:
18+
!IF "$(BUILD_LIB)" == "true"
19+
@cd "$(LIB_DIR)" && cd .. && $(MAKE) debug
20+
!ENDIF
21+
# Static with Debug info
22+
!IF "$(WEBUI_USE_TLS)" != "1"
23+
@echo Build C++ Example (Debug Static)...
24+
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
25+
!ENDIF
26+
# Dynamic with Debug info
27+
@echo Build C++ Example (Debug Dynamic)...
28+
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
29+
# Clean
30+
@- del *.exp >nul 2>&1
31+
@- del *.ilk >nul 2>&1
32+
@- del *.lib >nul 2>&1
33+
@- del *.obj >nul 2>&1
34+
@- del *.pdb >nul 2>&1
35+
@echo Done.
36+
37+
release:
38+
!IF "$(BUILD_LIB)" == "true"
39+
@cd "$(LIB_DIR)" && cd .. && $(MAKE)
40+
!ENDIF
41+
# Static Release
42+
!IF "$(WEBUI_USE_TLS)" != "1"
43+
@echo Build C++ Example (Release Static)...
44+
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
45+
!ENDIF
46+
# Dynamic Release
47+
@echo Build C++ Example (Release Dynamic)...
48+
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
49+
# Clean
50+
@- del *.exp >nul 2>&1
51+
@- del *.ilk >nul 2>&1
52+
@- del *.lib >nul 2>&1
53+
@- del *.obj >nul 2>&1
54+
@- del *.pdb >nul 2>&1
55+
@echo Done.
56+
57+
clean:
58+
- del *.obj >nul 2>&1
59+
- del *.ilk >nul 2>&1
60+
- del *.pdb >nul 2>&1
61+
- del *.exp >nul 2>&1
62+
- del *.exe >nul 2>&1
63+
- del *.lib >nul 2>&1
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// Call JavaScript from C++ Class Example
2+
3+
// Include the WebUI header
4+
#include "webui.hpp"
5+
6+
// Include C++ STD
7+
#include <iostream>
8+
#include <sstream>
9+
#include <stdexcept>
10+
#include <string>
11+
12+
class CounterApp
13+
{
14+
public:
15+
CounterApp()
16+
{
17+
// Bind HTML elements with class methods
18+
my_window.bind("my_function_count", this, &CounterApp::my_function_count);
19+
my_window.bind("Exit", this, &CounterApp::my_function_exit);
20+
}
21+
22+
void run()
23+
{
24+
// HTML
25+
const std::string my_html = R"V0G0N(
26+
<html>
27+
<head>
28+
<meta charset="UTF-8">
29+
<script src="/webui.js"></script>
30+
<title>Call JavaScript from C++ Class Example</title>
31+
<style>
32+
body {
33+
background: linear-gradient(to left, #36265a, #654da9);
34+
color: AliceBlue;
35+
font: 16px sans-serif;
36+
text-align: center;
37+
margin-top: 30px;
38+
}
39+
button {
40+
margin: 5px 0 10px;
41+
}
42+
</style>
43+
</head>
44+
<body>
45+
<h1>WebUI - Call JavaScript from C++ (Class)</h1>
46+
<br>
47+
<h1 id="count">0</h1>
48+
<br>
49+
<button id="ManualBtn" OnClick="my_function_count();">Manual Count</button>
50+
<br>
51+
<button id="AutoBtn" OnClick="AutoTest();">Auto Count (Every 10ms)</button>
52+
<br>
53+
<button id="Exit" OnClick="this.disabled=true;">Exit</button>
54+
<script>
55+
let count = 0;
56+
let auto_running = false;
57+
58+
function GetCount() {
59+
return count;
60+
}
61+
function SetCount(number) {
62+
document.getElementById('count').innerHTML = number;
63+
count = number;
64+
}
65+
function AutoTest(number) {
66+
if (auto_running) return;
67+
auto_running = true;
68+
document.getElementById('AutoBtn').disabled = true;
69+
document.getElementById('ManualBtn').disabled = true;
70+
71+
setInterval(function() {
72+
my_function_count();
73+
}, 10);
74+
}
75+
</script>
76+
</body>
77+
</html>
78+
)V0G0N";
79+
80+
// Set WebUI configuration to process UI events one at a time
81+
webui::set_config(ui_event_blocking, true);
82+
83+
// Show the window
84+
my_window.show(my_html); // my_window.show_browser(my_html, Chrome);
85+
86+
// Wait until all windows get closed
87+
webui::wait();
88+
}
89+
90+
private:
91+
webui::window my_window;
92+
93+
void my_function_exit(webui::window::event * /*e*/)
94+
{
95+
// Close all opened windows
96+
webui::exit();
97+
}
98+
99+
void my_function_count(webui::window::event *e)
100+
{
101+
// Create a buffer to hold the response
102+
char response[64];
103+
104+
// This is another way to create a buffer:
105+
// std::string buffer;
106+
// buffer.reserve(64);
107+
// my_window.script(..., ..., &buffer[0], 64);
108+
109+
// Run JavaScript
110+
if (!e->get_window().script("return GetCount();", 0, response, 64))
111+
{
112+
if (!e->get_window().is_shown())
113+
std::cout << "Window closed." << std::endl;
114+
else
115+
std::cout << "JavaScript Error: " << response << std::endl;
116+
return;
117+
}
118+
119+
// Get the count
120+
int count = std::stoi(response);
121+
122+
// Increment
123+
count++;
124+
125+
// Generate JavaScript
126+
std::stringstream js;
127+
js << "SetCount(" << count << ");";
128+
129+
// Run JavaScript (Quick Way)
130+
e->get_window().run(js.str());
131+
}
132+
};
133+
134+
int main()
135+
{
136+
CounterApp app;
137+
app.run();
138+
return 0;
139+
}
140+
141+
#if defined(_MSC_VER)
142+
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { main(); }
143+
#endif

0 commit comments

Comments
 (0)