[web] Added lib for web app

This commit is contained in:
Sidi Liang 2024-11-03 16:14:30 +08:00
parent 255f10dfae
commit b7176b39ed
No known key found for this signature in database
GPG Key ID: 9785F5EECFFA5311
3 changed files with 147 additions and 0 deletions

View File

@ -100,3 +100,15 @@ target_link_libraries(mat module-used-object)
add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp) add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp)
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src) target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(nasock module-used-object) 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
)

112
src/nasal_web.cpp Normal file
View File

@ -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 <string>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <cstdio>
#include <stdexcept>
struct NasalContext {
nasal::gc gc_instance;
std::unique_ptr<nasal::vm> vm_instance;
std::string last_result;
std::string last_error;
NasalContext() {
vm_instance = std::make_unique<nasal::vm>();
}
};
void* nasal_init() {
return new NasalContext();
}
void nasal_cleanup(void* context) {
delete static_cast<NasalContext*>(context);
}
const char* nasal_eval(void* context, const char* code) {
auto* ctx = static_cast<NasalContext*>(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<NasalContext*>(context);
return ctx->last_error.c_str();
}

23
src/nasal_web.h Normal file
View File

@ -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