From b7176b39eda7ed5f52c15752ae1dda2834a9dc16 Mon Sep 17 00:00:00 2001 From: Sidi Liang <1467329765@qq.com> Date: Sun, 3 Nov 2024 16:14:30 +0800 Subject: [PATCH] [web] Added lib for web app --- CMakeLists.txt | 12 +++++ src/nasal_web.cpp | 112 ++++++++++++++++++++++++++++++++++++++++++++++ src/nasal_web.h | 23 ++++++++++ 3 files changed, 147 insertions(+) create mode 100644 src/nasal_web.cpp create mode 100644 src/nasal_web.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6941632..1a58c3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,3 +100,15 @@ target_link_libraries(mat module-used-object) add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp) target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src) target_link_libraries(nasock module-used-object) + +# Add web library +add_library(nasal-web SHARED + src/nasal_web.cpp + ${NASAL_OBJECT_SOURCE_FILE} +) +target_include_directories(nasal-web PRIVATE ${CMAKE_SOURCE_DIR}/src) +set_target_properties(nasal-web PROPERTIES + C_VISIBILITY_PRESET hidden + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN ON +) diff --git a/src/nasal_web.cpp b/src/nasal_web.cpp new file mode 100644 index 0000000..cf13c58 --- /dev/null +++ b/src/nasal_web.cpp @@ -0,0 +1,112 @@ +#include "nasal_web.h" +#include "nasal_vm.h" +#include "nasal_parse.h" +#include "nasal_codegen.h" +#include "nasal_import.h" +#include "nasal_err.h" +#include "nasal_lexer.h" +#include +#include +#include +#include +#include +#include + +struct NasalContext { + nasal::gc gc_instance; + std::unique_ptr vm_instance; + std::string last_result; + std::string last_error; + + NasalContext() { + vm_instance = std::make_unique(); + } +}; + +void* nasal_init() { + return new NasalContext(); +} + +void nasal_cleanup(void* context) { + delete static_cast(context); +} + +const char* nasal_eval(void* context, const char* code) { + auto* ctx = static_cast(context); + + try { + nasal::lexer lex; + nasal::parse parse; + nasal::linker ld; + nasal::codegen gen; + + // Create a unique temporary file + char temp_filename[] = "/tmp/nasal_eval_XXXXXX.nasal"; + int fd = mkstemp(temp_filename); + if (fd == -1) { + throw std::runtime_error("Failed to create temporary file"); + } + + // Write the code to the temporary file + std::ofstream temp_file(temp_filename); + if (!temp_file.is_open()) { + close(fd); + throw std::runtime_error("Failed to open temporary file for writing"); + } + temp_file << code; + temp_file.close(); + close(fd); // Close the file descriptor + + // Capture stdout and stderr + std::stringstream output; + std::stringstream error_output; + std::streambuf* old_cout = std::cout.rdbuf(output.rdbuf()); + std::streambuf* old_cerr = std::cerr.rdbuf(error_output.rdbuf()); + + // Process the code by scanning the temporary file + if (lex.scan(std::string(temp_filename)).geterr()) { + ctx->last_error = error_output.str(); + std::cout.rdbuf(old_cout); + std::cerr.rdbuf(old_cerr); + // Remove the temporary file + std::remove(temp_filename); + return ctx->last_error.c_str(); + } + + if (parse.compile(lex).geterr()) { + ctx->last_error = error_output.str(); + std::cout.rdbuf(old_cout); + std::cerr.rdbuf(old_cerr); + // Remove the temporary file + std::remove(temp_filename); + return ctx->last_error.c_str(); + } + + ld.link(parse, false).chkerr(); + gen.compile(parse, ld, false, false).chkerr(); + + // Run the code + ctx->vm_instance->run(gen, ld, {}); + + // Restore stdout and stderr and get the outputs + std::cout.rdbuf(old_cout); + std::cerr.rdbuf(old_cerr); + ctx->last_result = output.str() + error_output.str(); + if (ctx->last_result.empty()) { + ctx->last_result = "Execution completed successfully."; + } + + // Remove the temporary file + std::remove(temp_filename); + + return ctx->last_result.c_str(); + } catch (const std::exception& e) { + ctx->last_error = e.what(); + return ctx->last_error.c_str(); + } +} + +const char* nasal_get_error(void* context) { + auto* ctx = static_cast(context); + return ctx->last_error.c_str(); +} diff --git a/src/nasal_web.h b/src/nasal_web.h new file mode 100644 index 0000000..f3c5eb5 --- /dev/null +++ b/src/nasal_web.h @@ -0,0 +1,23 @@ +#pragma once + +#include "nasal.h" + +#ifdef _WIN32 + #define NASAL_EXPORT __declspec(dllexport) +#else + #define NASAL_EXPORT __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Main API functions +NASAL_EXPORT void* nasal_init(); +NASAL_EXPORT void nasal_cleanup(void* context); +NASAL_EXPORT const char* nasal_eval(void* context, const char* code); +NASAL_EXPORT const char* nasal_get_error(void* context); + +#ifdef __cplusplus +} +#endif