windows....sigh
This commit is contained in:
BIN
private/lib/windows/x86_64/rktwebview.dll
Normal file
BIN
private/lib/windows/x86_64/rktwebview.dll
Normal file
Binary file not shown.
BIN
private/lib/windows/x86_64/rktwebview_prg.exe
Normal file
BIN
private/lib/windows/x86_64/rktwebview_prg.exe
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
private/lib/windows/x86_64/rktwebview_test.exe
Normal file
BIN
private/lib/windows/x86_64/rktwebview_test.exe
Normal file
Binary file not shown.
@@ -142,7 +142,12 @@
|
||||
(putenv "QTWEBENGINE_LOCALES_PATH"
|
||||
(path->string (build-path os-lib-dir "translations" "qtwebengine_locales")))
|
||||
(putenv "RKT_WEBVIEW_PRG"
|
||||
(let ((p
|
||||
(path->string (build-path os-lib-dir rktwebview-prg)))
|
||||
)
|
||||
(displayln p)
|
||||
p
|
||||
))
|
||||
(when (eq? os 'linux)
|
||||
(putenv "QT_QPA_PLATFORM" "xcb")
|
||||
(putenv "LD_LIBRARY_PATH"
|
||||
@@ -222,8 +227,19 @@
|
||||
eval_js_failed = 3
|
||||
no_devtools_on_platform = 4
|
||||
no_delegate_for_context = 5
|
||||
webview_missing_dependency = 6
|
||||
webview_canceled = 7
|
||||
webview_invalid_state = 8
|
||||
webview_invalid_argument = 9
|
||||
webview_unspecified = 10
|
||||
webview_dispatch_failed = 11
|
||||
move_failed = 12
|
||||
resize_failed = 13
|
||||
choose_dir_failed = 14
|
||||
open_file_failed = 15
|
||||
save_file_failed = 16
|
||||
failed = 17
|
||||
invalid_handle = 18
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ add_library(rktwebview SHARED
|
||||
rkt_protocol.h
|
||||
rktwebview_types.h
|
||||
json.cpp json.h
|
||||
utils.h
|
||||
)
|
||||
|
||||
add_executable(rktwebview_prg
|
||||
|
||||
@@ -62,8 +62,10 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
const char *me = argv[0];
|
||||
|
||||
fprintf(stderr, "%s runs\n", argv[0]);fflush(stderr);
|
||||
|
||||
if (argc < 6) {
|
||||
fprintf(stderr, "%s: wrong number of arguments\n", me);
|
||||
fprintf(stderr, "%s: wrong number of arguments\n", me);fflush(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -78,11 +80,11 @@ int main(int argc, char *argv[])
|
||||
int res_slot = atoi(res_slot_str);
|
||||
int evt_slot = atoi(evt_slot_str);
|
||||
|
||||
fprintf(stderr, "%s %s %s %s %s %s\n", me, shm_name, shm_size_str, cmd_slot_str, res_slot_str, evt_slot_str);
|
||||
fprintf(stderr, "%s %s %ld %d %d %d\n", me, shm_name, shm_size, cmd_slot, res_slot, evt_slot);
|
||||
fprintf(stderr, "%s %s %s %s %s %s\n", me, shm_name, shm_size_str, cmd_slot_str, res_slot_str, evt_slot_str);fflush(stderr);
|
||||
fprintf(stderr, "%s %s %ld %d %d %d\n", me, shm_name, shm_size, cmd_slot, res_slot, evt_slot);fflush(stderr);
|
||||
|
||||
if (!(shm_size > 0 && cmd_slot > 0 && res_slot > 0 && evt_slot > 0)) {
|
||||
fprintf(stderr, "%s: Invalid shm size or slots\n", me);
|
||||
fprintf(stderr, "%s: Invalid shm size or slots\n", me);fflush(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@@ -98,10 +100,10 @@ int main(int argc, char *argv[])
|
||||
handler->webview_handler->initApp();
|
||||
handler->webview_handler->execApp();
|
||||
|
||||
fprintf(stderr, "waiting for thread to end\n");
|
||||
fprintf(stderr, "waiting for thread to end\n");fflush(stderr);
|
||||
handler->wait();
|
||||
|
||||
fprintf(stderr, "cleaning up shm\n");
|
||||
fprintf(stderr, "cleaning up shm\n");fflush(stderr);
|
||||
|
||||
delete handler->webview_handler;
|
||||
delete handler->command_queue;
|
||||
@@ -318,7 +320,7 @@ void Handler::run()
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
fprintf(stderr, "Unknown command: %d\n", cmd);
|
||||
fprintf(stderr, "Unknown command: %d\n", cmd);fflush(stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,19 @@
|
||||
#include <chrono>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <filesystem>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <spawn.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "rktwebview.h"
|
||||
#include "rkt_protocol.h"
|
||||
#include <spawn.h>
|
||||
#include "shmqueue.h"
|
||||
#include "json.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define SHM_SIZE (10 * 1024 * 1024) // 10MB
|
||||
#define COMMAND_SLOT 1
|
||||
@@ -28,14 +34,26 @@ typedef struct {
|
||||
ShmQueue *command_queue;
|
||||
ShmQueue *command_result_queue;
|
||||
ShmQueue *event_queue;
|
||||
#ifdef _WIN32
|
||||
HANDLE rkt_webview_prg_pid;
|
||||
#else
|
||||
pid_t rkt_webview_prg_pid;
|
||||
#endif
|
||||
|
||||
bool rkt_webview_prg_started;
|
||||
bool valid;
|
||||
} Handle_t;
|
||||
|
||||
Handle_t *handler = nullptr;
|
||||
|
||||
static bool fileExists(const char *filename) {
|
||||
#ifdef _WIN32
|
||||
DWORD dwAttrib = GetFileAttributes(filename);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
#else
|
||||
return access(filename, X_OK) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t current_ms() {
|
||||
@@ -45,29 +63,62 @@ uint64_t current_ms() {
|
||||
|
||||
bool runRktWebview(Handle_t *handler)
|
||||
{
|
||||
// run rktwebview_prg using the environment variable RKT_WEBVIEW_PRG
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
char *rkt_webview_prg_path = getenv("RKT_WEBVIEW_PRG");
|
||||
if (rkt_webview_prg_path == nullptr) {
|
||||
fprintf(stderr, "RKT_WEBVIEW_PRG environment variable not set, cannot start webview program\n");
|
||||
fprintf(stderr, "RKT_WEBVIEW_PRG environment variable not set, cannot start webview program\n");fflush(stderr);
|
||||
return false;
|
||||
}
|
||||
if (!fileExists(rkt_webview_prg_path)) {
|
||||
fprintf(stderr, "%s does not exist or is not executable\n", rkt_webview_prg_path);
|
||||
fprintf(stderr, "%s does not exist or is not executable\n", rkt_webview_prg_path);fflush(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string path = basedir(rkt_webview_prg_path);
|
||||
|
||||
char shm_size_str[30];
|
||||
char command_slot[10];
|
||||
char command_result_slot[10];
|
||||
char event_slot[10];
|
||||
|
||||
sprintf(shm_size_str, "%ld", handler->shm_size);
|
||||
sprintf(shm_size_str, "%d", static_cast<int>(handler->shm_size));
|
||||
sprintf(command_slot, "%d", COMMAND_SLOT);
|
||||
sprintf(command_result_slot, "%d", COMMAND_RESULT_SLOT);
|
||||
sprintf(event_slot, "%d", EVENT_SLOT);
|
||||
|
||||
// run rktwebview_prg using the environment variable RKT_WEBVIEW_PRG
|
||||
#ifdef _WIN32
|
||||
|
||||
//STARTUPINFO si;
|
||||
//PROCESS_INFORMATION pi;
|
||||
//ZeroMemory( &si, sizeof(si) );
|
||||
//si.cb = sizeof(si);
|
||||
//ZeroMemory( &pi, sizeof(pi) );
|
||||
|
||||
std::string cmdargs = std::string("") + handler->name + " " + shm_size_str + " " + command_slot + " " + command_result_slot + " " + event_slot;
|
||||
std::string exe = std::string(rkt_webview_prg_path);
|
||||
|
||||
const char *td = getenv("TEMP");
|
||||
if (td == nullptr) { td = "C:\\"; }
|
||||
std::string tmpdir = td;
|
||||
std::string logfile = tmpdir + "\\" + "rktwebview.log"; //handler->name + ".log";
|
||||
std::string errfile = tmpdir + "\\" + "rktwebview.err";
|
||||
std::string redirect = " ^>" + logfile + " 2^>" + errfile;
|
||||
std::string cmdline = "start /b \"\" cmd /c \"" + exe + " " + cmdargs + " " + /*redirect*/ + "\"" + redirect;
|
||||
|
||||
char *cmdline_str = const_cast<char *>(cmdline.c_str());
|
||||
|
||||
auto cwd = std::filesystem::current_path();
|
||||
std::filesystem::current_path(path);
|
||||
int r = system(cmdline_str);
|
||||
std::filesystem::current_path(cwd);
|
||||
|
||||
//CreateProcessA(NULL, cmdline_str, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, path.c_str(), &si, &pi);
|
||||
handler->rkt_webview_prg_pid = 0;
|
||||
if (r != 0) {
|
||||
fprintf(stderr, "Cannot create process '%s' (error = %ld)\n", cmdline_str, GetLastError());fflush(stderr);
|
||||
}
|
||||
return (r == 0);
|
||||
#else
|
||||
char *argv[] = { rkt_webview_prg_path, const_cast<char *>(handler->name.c_str()), shm_size_str, command_slot, command_result_slot, event_slot, nullptr };
|
||||
|
||||
int r = posix_spawn(&handler->rkt_webview_prg_pid, rkt_webview_prg_path, nullptr, nullptr, argv, environ);
|
||||
@@ -108,20 +159,23 @@ void rkt_webview_cleanup()
|
||||
handler = nullptr;
|
||||
}
|
||||
*/
|
||||
fprintf(stderr, "Sending quit message\n");
|
||||
|
||||
if (handler->valid) {
|
||||
fprintf(stderr, "Sending quit message\n");fflush(stderr);
|
||||
handler->command_queue->enqueue(CMD_QUIT);
|
||||
fprintf(stderr, "Message sent\n");
|
||||
fprintf(stderr, "Message sent\n");fflush(stderr);
|
||||
bool stopped = false;
|
||||
while(!stopped) {
|
||||
int cmd;
|
||||
std::string s;
|
||||
fprintf(stderr, "Getting result of quit message\n");
|
||||
fprintf(stderr, "Getting result of quit message\n");fflush(stderr);
|
||||
handler->command_result_queue->dequeue(cmd, s, true);
|
||||
fprintf(stderr, "got %d\n", cmd);
|
||||
fprintf(stderr, "got %d\n", cmd);fflush(stderr);
|
||||
if (cmd == RESULT_QUIT) {
|
||||
stopped = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete handler->event_queue;
|
||||
delete handler->command_result_queue;
|
||||
@@ -140,16 +194,23 @@ void rkt_webview_init()
|
||||
char buf[1024];
|
||||
#ifdef DEBUG
|
||||
sprintf(buf, "rktwebview-dbg");
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
DWORD p = GetCurrentProcessId();
|
||||
sprintf(buf, "rktwebview-%ld", p);
|
||||
#else
|
||||
pid_t p = getpid();
|
||||
sprintf(buf, "rktwebview-%x", p);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
handler = new Handle_t;
|
||||
handler->valid = true;
|
||||
handler->name = buf;
|
||||
|
||||
handler->shm_size = SHM_SIZE;
|
||||
handler->shm = new Shm(handler->name.data(), handler->shm_size, true);
|
||||
if (!handler->shm->isValid()) { handler->valid = false; }
|
||||
handler->command_queue = new ShmQueue(handler->shm, COMMAND_SLOT, true);
|
||||
handler->command_result_queue = new ShmQueue(handler->shm, COMMAND_RESULT_SLOT, true);
|
||||
handler->event_queue = new ShmQueue(handler->shm, EVENT_SLOT, true);
|
||||
@@ -157,6 +218,7 @@ void rkt_webview_init()
|
||||
// Start rktwebview_prg application with the right information
|
||||
#ifndef DEBUG
|
||||
handler->rkt_webview_prg_started = runRktWebview(handler);
|
||||
if (!handler->rkt_webview_prg_started) { handler->valid = false; }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -164,7 +226,7 @@ void rkt_webview_init()
|
||||
bool rkt_webview_valid(rktwebview_t wv)
|
||||
{
|
||||
rkt_webview_init();
|
||||
if (handler != nullptr && handler->rkt_webview_prg_started) {
|
||||
if (handler != nullptr && handler->valid) {
|
||||
handler->command_queue->enqueue(CMD_HANDLE_IS_VALID);
|
||||
int result;
|
||||
std::string json_result;
|
||||
@@ -175,9 +237,21 @@ bool rkt_webview_valid(rktwebview_t wv)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool validHandle()
|
||||
{
|
||||
return (handler != nullptr) && handler->valid;
|
||||
}
|
||||
|
||||
#define FAIL_HANDLE if (!validHandle()) { return result_t::invalid_handle; }
|
||||
#define FAIL_CONTEXT if (!validHandle()) { return 0; }
|
||||
#define FAIL_WV if (!validHandle()) { return 0; }
|
||||
#define NOOP_HANDLE if (!validHandle()) { return; }
|
||||
#define FAIL_CALL_JS if (!validHandle()) { return nullptr; }
|
||||
|
||||
rkt_wv_context_t rkt_webview_new_context(const char *boilerplate_js, const char *optional_server_cert_pem)
|
||||
{
|
||||
rkt_webview_init();
|
||||
FAIL_CONTEXT
|
||||
|
||||
JSON j;
|
||||
|
||||
@@ -200,6 +274,8 @@ rkt_wv_context_t rkt_webview_new_context(const char *boilerplate_js, const char
|
||||
int rkt_webview_create(rkt_wv_context_t context, rktwebview_t parent)
|
||||
{
|
||||
rkt_webview_init();
|
||||
FAIL_WV
|
||||
|
||||
JSON j;
|
||||
j["context"] = context;
|
||||
j["parent"] = parent;
|
||||
@@ -216,6 +292,7 @@ int rkt_webview_create(rkt_wv_context_t context, rktwebview_t parent)
|
||||
void rkt_webview_close(rktwebview_t wv)
|
||||
{
|
||||
rkt_webview_init();
|
||||
NOOP_HANDLE
|
||||
|
||||
JSON j;
|
||||
j["wv"] = wv;
|
||||
@@ -224,6 +301,7 @@ void rkt_webview_close(rktwebview_t wv)
|
||||
|
||||
#define CMDRES4(cmd, wv, key, val, key2, val2, key3, val3, key4, val4) \
|
||||
rkt_webview_init(); \
|
||||
FAIL_HANDLE \
|
||||
JSON j; \
|
||||
j["wv"] = wv; \
|
||||
j[key] = val; \
|
||||
@@ -268,6 +346,7 @@ result_t rkt_webview_run_js(rktwebview_t wv, const char *js)
|
||||
rkt_data_t *rkt_webview_call_js(rktwebview_t wv, const char *js)
|
||||
{
|
||||
rkt_webview_init();
|
||||
FAIL_CALL_JS
|
||||
|
||||
JSON j;
|
||||
j["wv"] = wv;
|
||||
@@ -380,6 +459,7 @@ result_t rkt_webview_file_save(rktwebview_t w, const char *title, const char *ba
|
||||
void rkt_webview_set_ou_token(rktwebview_t wv, const char *token)
|
||||
{
|
||||
rkt_webview_init();
|
||||
NOOP_HANDLE
|
||||
|
||||
JSON j;
|
||||
j["wv"] = wv;
|
||||
@@ -401,7 +481,7 @@ void rkt_webview_free_data(rkt_data_t *d)
|
||||
free(d->data.js_result.value);
|
||||
free(d);
|
||||
} else {
|
||||
fprintf(stderr, "UNEXPECTED: data kind %d cannot be freed\n", d->kind);
|
||||
fprintf(stderr, "UNEXPECTED: data kind %d cannot be freed\n", d->kind);fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +520,7 @@ rkt_data_t *rkt_webview_get_event()
|
||||
memcpy(d->data.event.event, data.c_str(), ds);
|
||||
d->data.event.event[ds] = '\0';
|
||||
d->data.event.wv = wv;
|
||||
fprintf(stderr, "event: %d - '%s'\n", d->data.event.wv, d->data.event.event);
|
||||
//fprintf(stderr, "event: %d - '%s'\n", d->data.event.wv, d->data.event.event);fflush(stderr);
|
||||
return d;
|
||||
} else {
|
||||
return nullptr;
|
||||
|
||||
@@ -31,6 +31,7 @@ void Rktwebview_qt::processCommand(Command *cmd)
|
||||
switch(cmd->cmd) {
|
||||
case COMMAND_QUIT: { // Quit application
|
||||
_app->quit();
|
||||
cmd->done = true;
|
||||
}
|
||||
break;
|
||||
case COMMAND_NEW_CONTEXT: {
|
||||
@@ -640,6 +641,8 @@ void Rktwebview_qt::rktQuit()
|
||||
{
|
||||
Command c(COMMAND_QUIT);
|
||||
postCommand(&c);
|
||||
|
||||
while(!c.done) { doEvents(); }
|
||||
}
|
||||
|
||||
result_t Rktwebview_qt::fileDlg(rktwebview_t w, const char *title, const char *base, const char *filters,QFileDialog::FileMode mode, QFileDialog::AcceptMode am, QString evt_ok, QString evt_cancel)
|
||||
|
||||
@@ -1,16 +1,34 @@
|
||||
#include "rktwebview.h"
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{std::string me = argv[0];
|
||||
int idx = me.rfind("/");
|
||||
{
|
||||
std::string me = argv[0];
|
||||
|
||||
std::string loc = me.substr(0, idx);
|
||||
std::string loc = basedir(me);
|
||||
#ifdef _WIN32
|
||||
std::string prg = loc + "\\rktwebview_prg.exe";
|
||||
SetDllDirectoryA("C:\\Qt\\6.10.2\\msvc2022_64\\bin");
|
||||
#else
|
||||
std::string prg = loc + "/rktwebview_prg";
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
std::string e = std::string("RKT_WEBVIEW_PRG=") + prg;
|
||||
_putenv(e.c_str());
|
||||
}
|
||||
#else
|
||||
setenv("RKT_WEBVIEW_PRG", prg.c_str(), true);
|
||||
setenv("LD_LIBRARY_PATH", loc.c_str(), true);
|
||||
#endif
|
||||
|
||||
int context = rkt_webview_new_context("", nullptr);
|
||||
|
||||
@@ -24,7 +42,11 @@ int main(int argc, char *argv[])
|
||||
rkt_data_t *d = rkt_webview_get_event();
|
||||
rkt_webview_free_data(d);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
Sleep(10);
|
||||
#else
|
||||
sleep(10);
|
||||
#endif
|
||||
|
||||
rkt_webview_close(wv);
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ typedef enum {
|
||||
choose_dir_failed = 14,
|
||||
open_file_failed = 15,
|
||||
save_file_failed = 16,
|
||||
failed = 17
|
||||
failed = 17,
|
||||
invalid_handle = 18
|
||||
} result_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
#include "shm.h"
|
||||
|
||||
#ifdef __linux
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct __shm_item__ {
|
||||
|
||||
@@ -22,35 +11,26 @@ typedef struct __shm_item__ {
|
||||
} ShmItem;
|
||||
|
||||
|
||||
class ShmApi
|
||||
class ShmApiBase
|
||||
{
|
||||
private:
|
||||
int _shm_fd;
|
||||
size_t _size;
|
||||
bool _owner;
|
||||
void *_mem;
|
||||
sem_t *_sem;
|
||||
protected:
|
||||
char *_mem;
|
||||
|
||||
char *_mem_name;
|
||||
char *_sem_name;
|
||||
|
||||
size_t *_used;
|
||||
int *_used;
|
||||
ShmPlace *_slots;
|
||||
ShmPlace *_first;
|
||||
ShmPlace *_free_list;
|
||||
|
||||
char *_mem_name;
|
||||
char *_sem_name;
|
||||
|
||||
int _in_critical;
|
||||
|
||||
private:
|
||||
void cleanup() {
|
||||
// We don't need to do anything here.
|
||||
|
||||
}
|
||||
size_t _size;
|
||||
bool _owner;
|
||||
|
||||
public:
|
||||
ShmSem *makeSem(const char *name, bool owner) {
|
||||
return new ShmSem(name, owner);
|
||||
}
|
||||
virtual void enterCritical() = 0;
|
||||
virtual void leaveCritical() = 0;
|
||||
|
||||
public:
|
||||
int slot(int s) {
|
||||
@@ -71,7 +51,7 @@ public:
|
||||
if (place == SHM_NULL) {
|
||||
*p = nullptr;
|
||||
} else {
|
||||
*p = reinterpret_cast<T *>(reinterpret_cast<char *>(_mem) + place);
|
||||
*p = reinterpret_cast<T *>(_mem + place);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +61,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<char *>(_mem) + place;
|
||||
return _mem + place;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -125,7 +105,7 @@ public:
|
||||
} else {
|
||||
ShmPlace p_i = *_used;
|
||||
i = reinterpret_cast<ShmItem *>(reinterpret_cast<char *>(_mem) + p_i);
|
||||
size_t u = *_used + sizeof(ShmItem) + bytes;
|
||||
int u = static_cast<int>(*_used + sizeof(ShmItem) + bytes);
|
||||
|
||||
if (u >= _size) {
|
||||
place = SHM_NULL;
|
||||
@@ -185,6 +165,66 @@ public:
|
||||
leaveCritical();
|
||||
}
|
||||
|
||||
public:
|
||||
ShmSem *makeSem(const char *name, bool owner) {
|
||||
return new ShmSem(name, owner);
|
||||
}
|
||||
|
||||
public:
|
||||
ShmApiBase(const char *name, size_t size, bool owner) {
|
||||
char *buf = reinterpret_cast<char *>(malloc(strlen(name) + 50));
|
||||
sprintf(buf, "sem_%s", name);
|
||||
_sem_name = _strdup(buf);
|
||||
_mem_name = _strdup(name);
|
||||
::free(buf);
|
||||
|
||||
_owner = owner;
|
||||
|
||||
_size = size;
|
||||
|
||||
_used = nullptr;
|
||||
_slots = nullptr;
|
||||
_first = nullptr;
|
||||
_free_list = nullptr;
|
||||
_mem = nullptr;
|
||||
|
||||
_in_critical = 0;
|
||||
}
|
||||
|
||||
virtual ~ShmApiBase()
|
||||
{
|
||||
::free(_sem_name);
|
||||
::free(_mem_name);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __linux
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
|
||||
class ShmApi : public ShmApiBase
|
||||
{
|
||||
private:
|
||||
int _shm_fd;
|
||||
sem_t *_sem;
|
||||
|
||||
private:
|
||||
void cleanup() {
|
||||
// We don't need to do anything here.
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
void enterCritical() {
|
||||
if (_in_critical > 0) {
|
||||
_in_critical++;
|
||||
@@ -204,19 +244,17 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
ShmApi(const char *name, size_t size, bool owner) {
|
||||
|
||||
{
|
||||
char buf[strlen(name) + 50];
|
||||
sprintf(buf, "sem_%s", name);
|
||||
_sem_name = strdup(buf);
|
||||
_mem_name = strdup(name);
|
||||
bool isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
ShmApi(const char *name, size_t size, bool owner) : ShmApiBase(name, size, owner)
|
||||
{
|
||||
size_t slots_size = sizeof(ShmPlace) * SHM_MAX_SLOTS;
|
||||
size += slots_size;
|
||||
|
||||
if (owner) {
|
||||
if (_owner) {
|
||||
_sem = sem_open(_sem_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
|
||||
_shm_fd = shm_open(name, O_CREAT | O_RDWR, 0600);
|
||||
ftruncate(_shm_fd, size);
|
||||
@@ -224,21 +262,18 @@ public:
|
||||
_sem = sem_open(_sem_name, O_RDWR, S_IRUSR | S_IWUSR, 0);
|
||||
_shm_fd = shm_open(name, O_RDWR, 0600);
|
||||
}
|
||||
_size = size;
|
||||
_mem = mmap(nullptr, _size, PROT_READ|PROT_WRITE, MAP_SHARED, _shm_fd, 0);
|
||||
|
||||
_slots = reinterpret_cast <ShmPlace *>(reinterpret_cast<char *>(_mem) + sizeof(size_t) + sizeof(ShmPlace) + sizeof(ShmPlace));
|
||||
_used = reinterpret_cast<size_t *>(_mem);
|
||||
_slots = reinterpret_cast <ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace) + sizeof(ShmPlace));
|
||||
_used = reinterpret_cast<int *>(_mem);
|
||||
|
||||
_first = reinterpret_cast<ShmPlace *>(reinterpret_cast<char *>(_mem) + sizeof(size_t));
|
||||
_free_list = reinterpret_cast<ShmPlace *>(reinterpret_cast<char *>(_mem) + sizeof(size_t) + sizeof(ShmPlace));
|
||||
|
||||
_owner = owner;
|
||||
_first = reinterpret_cast<ShmPlace *>(_mem + sizeof(int));
|
||||
_free_list = reinterpret_cast<ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace));
|
||||
|
||||
if (_owner) {
|
||||
*_first = SHM_NULL;
|
||||
*_free_list = SHM_NULL;
|
||||
*_used = sizeof(size_t) + sizeof(ShmItem *) + sizeof(ShmItem *) + slots_size;
|
||||
*_used = sizeof(int) + sizeof(ShmItem *) + sizeof(ShmItem *) + slots_size;
|
||||
sem_post(_sem);
|
||||
}
|
||||
|
||||
@@ -254,44 +289,241 @@ public:
|
||||
shm_unlink(_mem_name);
|
||||
sem_unlink(_sem_name);
|
||||
}
|
||||
::free(_mem_name);
|
||||
::free(_sem_name);
|
||||
}
|
||||
};
|
||||
|
||||
class ShmSemApi {
|
||||
private:
|
||||
sem_t *_sem;
|
||||
char *_name;
|
||||
bool _owner;
|
||||
|
||||
public:
|
||||
void post() {
|
||||
sem_post(_sem);
|
||||
}
|
||||
|
||||
void wait() {
|
||||
int r = sem_wait(_sem);
|
||||
if (r != 0) {
|
||||
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
bool trywait() {
|
||||
int r = sem_trywait(reinterpret_cast<sem_t *>(_sem));
|
||||
if (r != 0 && r != EAGAIN) {
|
||||
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
|
||||
}
|
||||
|
||||
return (r == 0);
|
||||
}
|
||||
|
||||
public:
|
||||
ShmSemApi(const char *n, bool owner) {
|
||||
_name = strdup(n);
|
||||
|
||||
sem_t *s;
|
||||
if (owner) {
|
||||
s = sem_open(n, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
|
||||
} else {
|
||||
s = sem_open(n, O_RDWR, S_IRUSR | S_IWUSR, 0);
|
||||
}
|
||||
_sem = s;
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
virtual ~ShmSemApi() {
|
||||
sem_close(_sem);
|
||||
if (_owner) {
|
||||
sem_unlink(_name);
|
||||
}
|
||||
free(_name);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
class ShmApi
|
||||
#include <windows.h>
|
||||
|
||||
class ShmApi : public ShmApiBase
|
||||
{
|
||||
private:
|
||||
HANDLE _shm_handle;
|
||||
HANDLE _sem_handle;
|
||||
bool _valid;
|
||||
|
||||
public:
|
||||
ShmApi(const char *name, size_t size, bool owner)
|
||||
ShmApi(const char *name, size_t size, bool owner) : ShmApiBase(name, size, owner)
|
||||
{
|
||||
size_t slots_size = sizeof(ShmPlace) * SHM_MAX_SLOTS;
|
||||
size += slots_size;
|
||||
|
||||
_valid = true;
|
||||
if (_owner) {
|
||||
_shm_handle = CreateFileMappingA(INVALID_HANDLE_VALUE,
|
||||
NULL,
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
static_cast<DWORD>(size), // size must be smaller < 2GB
|
||||
name);
|
||||
|
||||
if (_shm_handle == NULL) {
|
||||
fprintf(stderr, "Cannot create shared memory with name %s and size %lld\n", name, size);
|
||||
_valid = false;
|
||||
}
|
||||
} else {
|
||||
_shm_handle = OpenFileMappingA(FILE_MAP_ALL_ACCESS,
|
||||
FALSE,
|
||||
name);
|
||||
if (_shm_handle == NULL) {
|
||||
fprintf(stderr, "Cannot open shared memory with name %s\n", name);
|
||||
_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_valid) {
|
||||
_mem = static_cast<LPSTR>(MapViewOfFile(_shm_handle,
|
||||
FILE_MAP_ALL_ACCESS,
|
||||
0,
|
||||
0,
|
||||
size));
|
||||
if (_mem == NULL) {
|
||||
fprintf(stderr, "Cannot map shared memory, errorcode = %ld\n", GetLastError());
|
||||
_valid = false;
|
||||
CloseHandle(_shm_handle);
|
||||
}
|
||||
}
|
||||
|
||||
if (_valid) {
|
||||
if (_owner) {
|
||||
_sem_handle = CreateSemaphoreA(NULL,
|
||||
1,
|
||||
10000,
|
||||
_sem_name
|
||||
);
|
||||
} else {
|
||||
_sem_handle = OpenSemaphoreA(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, FALSE, _sem_name);
|
||||
}
|
||||
if (_sem_handle == NULL) {
|
||||
fprintf(stderr, "Cannot create or open semaphore with name '%s' (%ld)\n", _sem_name, GetLastError());
|
||||
UnmapViewOfFile(_mem);
|
||||
CloseHandle(_shm_handle);
|
||||
_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_valid) {
|
||||
_slots = reinterpret_cast <ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace) + sizeof(ShmPlace));
|
||||
_used = reinterpret_cast<int *>(_mem);
|
||||
|
||||
_first = reinterpret_cast<ShmPlace *>(_mem + sizeof(int));
|
||||
_free_list = reinterpret_cast<ShmPlace *>(_mem + sizeof(int) + sizeof(ShmPlace));
|
||||
|
||||
if (_owner) {
|
||||
*_first = SHM_NULL;
|
||||
*_free_list = SHM_NULL;
|
||||
*_used = sizeof(int) + sizeof(ShmItem *) + sizeof(ShmItem *) + slots_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~ShmApi()
|
||||
{
|
||||
if (_valid) {
|
||||
UnmapViewOfFile(_mem);
|
||||
CloseHandle(_shm_handle);
|
||||
CloseHandle(_sem_handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
return _valid;
|
||||
}
|
||||
|
||||
void enterCritical()
|
||||
{
|
||||
|
||||
if (_in_critical > 0) {
|
||||
_in_critical++;
|
||||
} else {
|
||||
WaitForSingleObject(_sem_handle, INFINITE);
|
||||
_in_critical = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void leaveCritical()
|
||||
{
|
||||
|
||||
if (_in_critical > 1) {
|
||||
_in_critical--;
|
||||
} else {
|
||||
_in_critical = 0;
|
||||
ReleaseSemaphore(_sem_handle, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void *alloc(size_t bytes)
|
||||
ShmSem *sem(const char *name, bool owner)
|
||||
{
|
||||
return malloc(bytes);
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ShmSemApi {
|
||||
private:
|
||||
HANDLE _sem;
|
||||
char *_name;
|
||||
bool _owner;
|
||||
|
||||
public:
|
||||
void post() {
|
||||
ReleaseSemaphore(_sem, 1, NULL);
|
||||
}
|
||||
|
||||
void free(void *mem)
|
||||
{
|
||||
free(mem);
|
||||
void wait() {
|
||||
DWORD r = WaitForSingleObject(_sem, INFINITE);
|
||||
if (r != WAIT_OBJECT_0) {
|
||||
fprintf(stderr, "sem_wait error: %ld\n", r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool trywait() {
|
||||
DWORD r = WaitForSingleObject(_sem , 0);
|
||||
if (r != WAIT_OBJECT_0 && r != WAIT_TIMEOUT) {
|
||||
fprintf(stderr, "sem_wait error: %ld\n", r);
|
||||
}
|
||||
return r == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
public:
|
||||
ShmSemApi(const char *n, bool owner) {
|
||||
_name = _strdup(n);
|
||||
|
||||
if (owner) {
|
||||
_sem = CreateSemaphoreA(NULL,
|
||||
0,
|
||||
10000,
|
||||
_name);
|
||||
} else {
|
||||
_sem = OpenSemaphoreA(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, FALSE, _name);
|
||||
}
|
||||
|
||||
if (_sem == NULL) {
|
||||
fprintf(stderr, "Cannot create or open semaphore with name '%s'\n", _name);
|
||||
}
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
virtual ~ShmSemApi() {
|
||||
if (_sem != NULL) {
|
||||
CloseHandle(_sem);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -326,6 +558,11 @@ ShmSem *Shm::sem(const char *name, bool owner)
|
||||
return _shm_api->makeSem(name, owner);
|
||||
}
|
||||
|
||||
bool Shm::isValid()
|
||||
{
|
||||
return _shm_api->isValid();
|
||||
}
|
||||
|
||||
const char *Shm::name()
|
||||
{
|
||||
return _shm_api->name();
|
||||
@@ -352,44 +589,22 @@ Shm::~Shm()
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ShmSem::post() {
|
||||
sem_post(reinterpret_cast<sem_t *>(_sem));
|
||||
_api->post();
|
||||
}
|
||||
|
||||
void ShmSem::wait() {
|
||||
int r = sem_wait(reinterpret_cast<sem_t *>(_sem));
|
||||
if (r != 0) {
|
||||
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
|
||||
}
|
||||
_api->wait();
|
||||
}
|
||||
|
||||
bool ShmSem::trywait() {
|
||||
int r = sem_trywait(reinterpret_cast<sem_t *>(_sem));
|
||||
if (r != 0 && r != EAGAIN) {
|
||||
fprintf(stderr, "sem_wait error: %d, %s\n", errno, strerror(errno));
|
||||
}
|
||||
|
||||
return (r == 0);
|
||||
return _api->trywait();
|
||||
}
|
||||
|
||||
ShmSem::ShmSem(const char *n, bool owner) {
|
||||
_name = strdup(n);
|
||||
|
||||
sem_t *s;
|
||||
if (owner) {
|
||||
s = sem_open(n, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, 0);
|
||||
} else {
|
||||
s = sem_open(n, O_RDWR, S_IRUSR | S_IWUSR, 0);
|
||||
}
|
||||
_sem = reinterpret_cast<void *>(s);
|
||||
_owner = owner;
|
||||
_api = new ShmSemApi(n, owner);
|
||||
}
|
||||
|
||||
ShmSem::~ShmSem() {
|
||||
sem_close(reinterpret_cast<sem_t *>(_sem));
|
||||
if (_owner) {
|
||||
sem_unlink(_name);
|
||||
}
|
||||
free(_name);
|
||||
delete _api;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
class ShmApi;
|
||||
class ShmSemApi;
|
||||
typedef int ShmPlace;
|
||||
typedef int ShmSlot;
|
||||
|
||||
@@ -12,9 +13,7 @@ typedef int ShmSlot;
|
||||
|
||||
class ShmSem {
|
||||
private:
|
||||
void *_sem;
|
||||
char *_name;
|
||||
bool _owner;
|
||||
ShmSemApi *_api;
|
||||
|
||||
public:
|
||||
void post();
|
||||
@@ -44,6 +43,9 @@ public:
|
||||
public:
|
||||
ShmSem *sem(const char *name, bool owner);
|
||||
|
||||
public:
|
||||
bool isValid();
|
||||
|
||||
public:
|
||||
const char *name();
|
||||
|
||||
|
||||
29
rktwebview_qt/utils.h
Normal file
29
rktwebview_qt/utils.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
inline std::string basedir(const std::string &path)
|
||||
{
|
||||
int idx1 = path.rfind("/");
|
||||
int idx2 = path.rfind("\\");
|
||||
std::string r;
|
||||
if (idx1 == std::string::npos && idx2 == std::string::npos) {
|
||||
r = "";
|
||||
} else {
|
||||
int idx;
|
||||
if (idx1 == std::string::npos) {
|
||||
idx = idx2;
|
||||
} else if (idx2 == std::string::npos) {
|
||||
idx = idx1;
|
||||
} else if (idx1 < idx2) {
|
||||
idx = idx2;
|
||||
} else {
|
||||
idx = idx1;
|
||||
}
|
||||
r = path.substr(0, idx);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif // UTILS_H
|
||||
Reference in New Issue
Block a user