feat: add WebAssembly (Emscripten) build support

- Platform detection: EMSCRIPTEN/WASM macros in piplatform.h
- CMake: PIP_WASM option, auto-detect, STATIC lib, pthread flags,
  disable incompatible modules (console, usb, fftw, opencl, lua,
  http_server, http_client, mqtt_client)
- Macros: environ, SHUT_RDWR, HAS_LOCALE off, PIP_MIN_MSLEEP=10ms
- System stubs: process, signals, library, systeminfo, hidevice
- IO stubs: serial, ethernet, can, sharedmemory
- Thread: gettid() fallback via pthread_self()
- Core: locale/init adjustments, console.log routing via EM_ASM
- Fix: toDecimal precision loss, unreachable code in createPipe
This commit is contained in:
2026-08-11 18:19:54 +03:00
parent 3ea5af750e
commit 75bab5a4b9
17 changed files with 564 additions and 327 deletions
+2 -5
View File
@@ -74,7 +74,6 @@ option(PIP_FFTW_F "Support fftw module for float" ON)
option(PIP_FFTW_L "Support fftw module for long double" ON)
option(PIP_FFTW_Q "Support fftw module for quad double" OFF)
option(PIP_MANUAL_TEST "Build dev test (main.cpp)" OFF)
option(PIP_WASM "Build for WebAssembly (Emscripten)" OFF)
set(PIP_UTILS 1)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_STANDARD 11)
@@ -230,10 +229,8 @@ if(PIP_FREERTOS)
set(LOCAL ON)
endif()
if(NOT PIP_WASM)
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten" OR DEFINED CMAKE_Emscripten)
set(PIP_WASM ON)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten" OR DEFINED CMAKE_Emscripten)
set(PIP_WASM ON)
endif()
if(PIP_WASM)
+6 -10
View File
@@ -195,7 +195,7 @@ extern long long __pi_perf_freq;
# ifndef SHUT_RDWR
# define SHUT_RDWR 2
# endif
#endif
#endif //EMSCRIPTEN
#ifndef DOXYGEN
@@ -210,13 +210,9 @@ extern long long __pi_perf_freq;
typedef long time_t;
# endif
# ifdef LINUX
# if defined(LINUX) || defined(EMSCRIPTEN)
# define environ __environ
# endif
# ifdef EMSCRIPTEN
# define environ __environ
# endif
# endif //EMSCRIPTEN
# ifdef FREE_BSD
extern char ** environ;
@@ -248,7 +244,7 @@ extern char ** environ;
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
# if defined(LINUX) && !defined(EMSCRIPTEN)
# define HAS_LOCALE
# endif
# endif //EMSCRIPTEN
# ifdef MAC_OS
# pragma GCC diagnostic ignored "-Wundefined-bool-conversion"
# pragma GCC diagnostic ignored "-Wc++11-extensions"
@@ -405,9 +401,9 @@ typedef long long ssize_t;
#ifndef PIP_MIN_MSLEEP
# if defined(MICRO_PIP) || defined(EMSCRIPTEN)
# define PIP_MIN_MSLEEP 10.
# else
# else //EMSCRIPTEN
# define PIP_MIN_MSLEEP 1.
# endif
# endif //EMSCRIPTEN
#endif
+34 -21
View File
@@ -236,9 +236,11 @@ PICout & PICout::operator<<(PICoutAction v) {
SetConsoleCursorPosition(__Private__::hOut, coord);
printf(" ");
SetConsoleCursorPosition(__Private__::hOut, coord);
#elif !defined(EMSCRIPTEN)
#else //EMSCRIPTEN
# ifndef EMSCRIPTEN
printf("\e[1D \e[1D");
#endif
# endif //EMSCRIPTEN
#endif //EMSCRIPTEN
}
break;
case PICoutManipulators::ShowCursor:
@@ -247,9 +249,11 @@ PICout & PICout::operator<<(PICoutAction v) {
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = true;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
#elif !defined(EMSCRIPTEN)
#else //EMSCRIPTEN
# ifndef EMSCRIPTEN
printf("\e[?25h");
#endif
# endif //EMSCRIPTEN
#endif //EMSCRIPTEN
}
break;
case PICoutManipulators::HideCursor:
@@ -258,9 +262,11 @@ PICout & PICout::operator<<(PICoutAction v) {
GetConsoleCursorInfo(__Private__::hOut, &curinfo);
curinfo.bVisible = false;
SetConsoleCursorInfo(__Private__::hOut, &curinfo);
#elif !defined(EMSCRIPTEN)
#else //EMSCRIPTEN
# ifndef EMSCRIPTEN
printf("\e[?25l");
#endif
# endif //EMSCRIPTEN
#endif //EMSCRIPTEN
}
break;
case PICoutManipulators::ClearLine:
@@ -279,18 +285,22 @@ PICout & PICout::operator<<(PICoutAction v) {
delete[] line;
}
SetConsoleCursorPosition(__Private__::hOut, coord);
#elif !defined(EMSCRIPTEN)
#else //EMSCRIPTEN
# ifndef EMSCRIPTEN
printf("\e[0G\e[K");
#endif
# endif //EMSCRIPTEN
#endif //EMSCRIPTEN
}
break;
case PICoutManipulators::ClearScreen:
if (isOutputDeviceActive(Console)) {
#ifdef WINDOWS
/// TODO : wondows ClearScreen !!!
#elif !defined(EMSCRIPTEN)
#else //EMSCRIPTEN
# ifndef EMSCRIPTEN
printf("\e[H\e[J");
#endif
# endif //EMSCRIPTEN
#endif //EMSCRIPTEN
}
break;
case PICoutManipulators::SaveContol: saveControls(); break;
@@ -378,14 +388,16 @@ void PICout::stdoutPIString(const PIString & str, PICoutStdStream s) {
},
buf,
(int)s);
#elif defined(HAS_LOCALE)
#else //EMSCRIPTEN
# ifdef HAS_LOCALE
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> utf8conv;
getStdStream(s) << utf8conv.to_bytes((char16_t *)&(const_cast<PIString &>(str).front()),
(char16_t *)&(const_cast<PIString &>(str).front()) + str.size());
#else
# else // HAS_LOCALE
for (PIChar c: str)
getStdWStream(s).put(c.toWChar());
#endif
# endif // HAS_LOCALE
#endif //EMSCRIPTEN
}
@@ -410,9 +422,9 @@ PICout & PICout::write(const char * str, int len) {
0,
(int)stream_);
}
#else
#else //EMSCRIPTEN
if (isOutputDeviceActive(Console)) getStdStream(stream_).write(str, len);
#endif
#endif //EMSCRIPTEN
if (isOutputDeviceActive(Buffer)) PICout::__string__().append(PIString(str, len));
}
return *this;
@@ -437,9 +449,9 @@ void PICout::writeChar(char c) {
} else {
#ifdef EMSCRIPTEN
if (isOutputDeviceActive(Console)) fputc(c, stream_ == PICoutStdStream::StdErr ? stderr : stdout);
#else
#else //EMSCRIPTEN
if (isOutputDeviceActive(Console)) getStdStream(stream_) << c;
#endif
#endif //EMSCRIPTEN
if (isOutputDeviceActive(Buffer)) PICout::__string__().append(c);
}
}
@@ -682,9 +694,9 @@ void PICout::applyFormat(PICoutFormat f) {
if (buffer_ || !isOutputDeviceActive(Console)) return;
#ifdef EMSCRIPTEN
return;
#endif
#else //EMSCRIPTEN
format_changed_ = true;
#ifdef WINDOWS
# ifdef WINDOWS
static int mask_fore = ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
static int mask_back = ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
switch (f) {
@@ -714,7 +726,7 @@ void PICout::applyFormat(PICoutFormat f) {
default: break;
}
SetConsoleTextAttribute(__Private__::hOut, win_attr_);
#else
# else
switch (f) {
case Bin:
case Oct:
@@ -744,7 +756,8 @@ void PICout::applyFormat(PICoutFormat f) {
case PICoutManipulators::Default: printf("\e[0m"); break;
default: break;
}
#endif
# endif
#endif //EMSCRIPTEN
}
+2 -2
View File
@@ -40,9 +40,9 @@ double piMountInfoRefreshIntervalMs = 10000.;
lconv * currentLocale =
#if defined(ANDROID) || defined(EMSCRIPTEN)
0;
#else
#else //EMSCRIPTEN
std::localeconv();
#endif
#endif //EMSCRIPTEN
#ifdef MAC_OS
clock_serv_t __pi_mac_clock;
+1 -1
View File
@@ -58,7 +58,7 @@ typedef LONG(NTAPI * PINtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
#ifdef EMSCRIPTEN
# include <emscripten.h>
# include <emscripten/html5.h>
#endif
#endif //EMSCRIPTEN
// clang-format on
+10 -10
View File
@@ -50,7 +50,7 @@ void __PISetTimerResolution() {
# include <pthread.h>
# ifndef EMSCRIPTEN
# include <pwd.h>
# endif
# endif //EMSCRIPTEN
# include <sys/utsname.h>
# ifdef BLACKBERRY
# include <signal.h>
@@ -116,8 +116,8 @@ PIInit::PIInit() {
break;
}
}
# endif
# else // WINDOWS
# endif //EMSCRIPTEN
# else // WINDOWS
// OS version
DWORD dwVersion = GetVersion();
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
@@ -143,7 +143,7 @@ PIInit::PIInit() {
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
__PISetTimerResolution();
}
# endif // WINDOWS
# endif // WINDOWS
# ifdef HAS_LOCALE
// std::cout << "has locale" << std::endl;
if (currentLocale_t != 0) {
@@ -156,9 +156,9 @@ PIInit::PIInit() {
# ifndef EMSCRIPTEN
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
# endif
# endif // HAS_LOCALE
# endif // ANDROID
# endif //EMSCRIPTEN
# endif // HAS_LOCALE
# endif // ANDROID
PRIVATE->delete_locs = false;
__syslocname__ = __sysoemname__ = 0;
__utf8name__ = const_cast<char *>("UTF-8");
@@ -235,12 +235,12 @@ PIInit::PIInit() {
sinfo->OS_version = uns.release;
sinfo->architecture = uns.machine;
}
# else
# else //EMSCRIPTEN
sinfo->processorsCount = 1;
sinfo->OS_version = PIStringAscii("WASM");
sinfo->architecture = PIStringAscii("wasm32");
# endif
# endif // WINDOWS
# endif //EMSCRIPTEN
# endif // WINDOWS
# ifdef ESP_PLATFORM
esp_chip_info_t chip_info;
+102 -111
View File
@@ -73,7 +73,7 @@
# endif
# endif
#endif
#endif
#endif //EMSCRIPTEN
// clang-format on
#include "piwaitevent_p.h"
@@ -110,7 +110,7 @@ PIString getSockAddr(sockaddr * s) {
const char * r = inet_ntop(AF_INET, &((sockaddr_in *)s)->sin_addr, buf, sizeof(buf));
return r ? PIStringAscii(r) : PIString();
}
#endif
#endif // WINDOWS, EMSCRIPTEN
REGISTER_DEVICE(PIEthernet)
@@ -121,7 +121,7 @@ PRIVATE_DEFINITION_START(PIEthernet)
sockaddr_in addr_;
sockaddr_in saddr_;
sockaddr_in raddr_;
#endif
#endif // EMSCRIPTEN
PIWaitEvent event;
PRIVATE_DEFINITION_END(PIEthernet)
@@ -158,7 +158,7 @@ PIEthernet::PIEthernet(int sock_, PIString ip_port): PIIODevice("", ReadWrite) {
setPath(ip_port);
#ifndef EMSCRIPTEN
ethNonblocking(sock);
#endif
#endif // EMSCRIPTEN
PRIVATE->event.create();
// piCoutObj << "new tcp client" << sock_;
}
@@ -218,8 +218,7 @@ void PIEthernet::construct() {
void PIEthernet::init() {
#ifdef EMSCRIPTEN
return;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (isOpened() || is_server_client) return;
if (sock != -1) return;
// piCout << "init " << type();
@@ -252,7 +251,7 @@ void PIEthernet::init() {
applyBuffers();
applyOptInt(IPPROTO_IP, IP_TTL, TTL());
// piCoutObj << "inited" << path();
#endif
#endif // EMSCRIPTEN
}
@@ -278,11 +277,11 @@ PIByteArray PIEthernet::macToBytes(const PIString & mac) {
PIString PIEthernet::applyMask(const PIString & ip, const PIString & mask) {
#ifdef EMSCRIPTEN
return PIString();
#else
#else // EMSCRIPTEN
struct in_addr ia;
ia.s_addr = inet_addr(ip.dataAscii()) & inet_addr(mask.dataAscii());
return PIStringAscii(inet_ntoa(ia));
#endif
#endif // EMSCRIPTEN
}
@@ -296,11 +295,11 @@ PINetworkAddress PIEthernet::applyMask(const PINetworkAddress & ip, const PINetw
PIString PIEthernet::getBroadcast(const PIString & ip, const PIString & mask) {
#ifdef EMSCRIPTEN
return PIString();
#else
#else // EMSCRIPTEN
struct in_addr ia;
ia.s_addr = inet_addr(ip.dataAscii()) | ~inet_addr(mask.dataAscii());
return PIStringAscii(inet_ntoa(ia));
#endif
#endif // EMSCRIPTEN
}
@@ -314,8 +313,7 @@ PINetworkAddress PIEthernet::getBroadcast(const PINetworkAddress & ip, const PIN
bool PIEthernet::openDevice() {
#ifdef EMSCRIPTEN
return false;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (connected_) return true;
// piCoutObj << "open";
init();
@@ -335,7 +333,7 @@ bool PIEthernet::openDevice() {
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
# endif
// piCout << "bind to" << (params[PIEthernet::Broadcast] ? "255.255.255.255" : ip_) << ":" << port_ << " ...";
int tries = 0;
int tries = 0;
while ((bind(sock, (sockaddr *)&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
init();
tries++;
@@ -352,7 +350,7 @@ bool PIEthernet::openDevice() {
applyOptInt(IPPROTO_IP, IP_TTL, TTL());
addr_lr.clear();
return true;
#endif
#endif // EMSCRIPTEN
}
@@ -383,8 +381,7 @@ void PIEthernet::closeSocket(int & sd) {
void PIEthernet::applyTimeouts() {
#ifdef EMSCRIPTEN
return;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (sock < 0) return;
PISystemTime rtm = readTimeout(), wtm = writeTimeout();
applyTimeout(sock, SO_RCVTIMEO, rtm);
@@ -393,7 +390,7 @@ void PIEthernet::applyTimeouts() {
applyTimeout(sock_s, SO_RCVTIMEO, rtm);
applyTimeout(sock_s, SO_SNDTIMEO, wtm);
}
#endif
#endif // EMSCRIPTEN
}
@@ -408,7 +405,7 @@ void PIEthernet::applyBuffers() {
ethSetsockoptInt(sock, SOL_SOCKET, SO_SNDBUF, snd_buf);
}
}
#endif
#endif // EMSCRIPTEN
}
@@ -416,9 +413,8 @@ void PIEthernet::applyTimeout(int fd, int opt, PISystemTime tm) {
if (fd == 0) return;
#ifdef EMSCRIPTEN
return;
#endif
#ifndef EMSCRIPTEN
// piCoutObj << "setReadIsBlocking" << yes;
#else // EMSCRIPTEN
// piCoutObj << "setReadIsBlocking" << yes;
# ifdef WINDOWS
DWORD _tm = tm.toMilliseconds();
# else
@@ -427,7 +423,7 @@ void PIEthernet::applyTimeout(int fd, int opt, PISystemTime tm) {
_tm.tv_usec = tm.nanoseconds / 1000;
# endif
ethSetsockopt(fd, SOL_SOCKET, opt, &_tm, sizeof(_tm));
#endif
#endif // EMSCRIPTEN
}
@@ -440,8 +436,7 @@ void PIEthernet::applyOptInt(int level, int opt, int val) {
bool PIEthernet::joinMulticastGroup(const PIString & group) {
#ifdef EMSCRIPTEN
return false;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (sock == -1) init();
if (sock == -1) return false;
if (type() != UDP) {
@@ -490,15 +485,14 @@ bool PIEthernet::joinMulticastGroup(const PIString & group) {
applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL());
if (!mcast_groups.contains(group)) mcast_groups << group;
return true;
#endif
#endif // EMSCRIPTEN
}
bool PIEthernet::leaveMulticastGroup(const PIString & group) {
#ifdef EMSCRIPTEN
return false;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (sock == -1) init();
if (sock == -1) return false;
if (type() != UDP) {
@@ -531,15 +525,14 @@ bool PIEthernet::leaveMulticastGroup(const PIString & group) {
}
mcast_groups.removeAll(group);
return true;
#endif
#endif // EMSCRIPTEN
}
bool PIEthernet::connect(bool threaded) {
#ifdef EMSCRIPTEN
return false;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (threaded) {
connecting_ = true;
return true;
@@ -553,11 +546,11 @@ bool PIEthernet::connect(bool threaded) {
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
# endif
connecting_ = true;
connected_ = connectTCP();
connecting_ = false;
connecting_ = true;
connected_ = connectTCP();
connecting_ = false;
if (!connected_) {
piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
}
@@ -566,15 +559,14 @@ bool PIEthernet::connect(bool threaded) {
connected();
}
return connected_;
#endif
#endif // EMSCRIPTEN
}
bool PIEthernet::listen(bool threaded) {
#ifdef EMSCRIPTEN
return false;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (sock == -1) init();
if (sock == -1) return false;
if (threaded) {
@@ -596,10 +588,10 @@ bool PIEthernet::listen(bool threaded) {
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
# endif
opened_ = false;
int tries = 0;
opened_ = false;
int tries = 0;
while ((bind(sock, (sockaddr *)&PRIVATE->addr_, sizeof(PRIVATE->addr_)) == -1) && (tries < 2)) {
init();
tries++;
@@ -616,7 +608,7 @@ bool PIEthernet::listen(bool threaded) {
piCoutObj << "listen on" << path();
server_thread_.start(server_func);
return true;
#endif
#endif // EMSCRIPTEN
}
@@ -711,8 +703,7 @@ void PIEthernet::interrupt() {
ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
#ifdef EMSCRIPTEN
return -1;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
// piCout << "read" << sock;
if (sock == -1) init();
if (sock == -1 || read_to == 0) return -1;
@@ -727,10 +718,10 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
# endif
// piCoutObj << "connect to " << path() << "...";
connected_ = connectTCP();
connected_ = connectTCP();
// piCoutObj << "connect to " << path() << connected_;
if (!connected_) piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
opened_.exchange(connected_);
@@ -838,15 +829,14 @@ ssize_t PIEthernet::readDevice(void * read_to, ssize_t max_size) {
default: break;
}
return -1;
#endif
#endif // EMSCRIPTEN
}
ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
#ifdef EMSCRIPTEN
return -1;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
if (sock == -1) init();
if (sock == -1 || !isWriteable()) {
// piCoutObj << "Can`t send to uninitialized socket";
@@ -880,10 +870,10 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
PRIVATE->addr_.sin_addr.s_addr = addr_r.ip();
PRIVATE->addr_.sin_family = AF_INET;
# ifdef QNX
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
PRIVATE->addr_.sin_len = sizeof(PRIVATE->addr_);
# endif
// piCoutObj << "connect to " << ip << ":" << port_;
connected_ = connectTCP();
connected_ = connectTCP();
if (!connected_) piCoutObj << "Can`t connect to" << addr_r << "," << ethErrorString();
opened_.exchange(connected_);
if (connected_) {
@@ -940,7 +930,7 @@ ssize_t PIEthernet::writeDevice(const void * data, ssize_t max_size) {
default: break;
}
return -1;
#endif
#endif // EMSCRIPTEN
}
@@ -961,7 +951,7 @@ void PIEthernet::applyParameters() {
if (params[PIEthernet::ReuseAddress]) ethSetsockoptBool(sock, SOL_SOCKET, SO_REUSEADDR);
if (params[PIEthernet::Broadcast]) ethSetsockoptBool(sock, SOL_SOCKET, SO_BROADCAST);
if (params[PIEthernet::NoDelay] && (type() == TCP_Client)) ethSetsockoptBool(sock, IPPROTO_TCP, TCP_NODELAY, true);
#endif
#endif // EMSCRIPTEN
}
@@ -974,8 +964,7 @@ void PIEthernet::clientDeleted(PIObject * o) {
void PIEthernet::server_func(void * eth) {
#ifdef EMSCRIPTEN
return;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
PIEthernet * ce = (PIEthernet *)eth;
if (ce->listen_threaded) {
if (!ce->server_bounded) {
@@ -989,7 +978,7 @@ void PIEthernet::server_func(void * eth) {
sockaddr_in client_addr;
socklen_t slen = sizeof(client_addr);
# ifdef WINDOWS
long wr = ce->waitForEvent(ce->PRIVATEWB->event, FD_ACCEPT | FD_CLOSE);
long wr = ce->waitForEvent(ce->PRIVATEWB->event, FD_ACCEPT | FD_CLOSE);
if (wr != FD_ACCEPT) {
piMSleep(10);
return;
@@ -1030,7 +1019,7 @@ void PIEthernet::server_func(void * eth) {
ce->clients_mutex.unlock();
ce->newConnection(e);
// cout << "connected " << ip << endl;
#endif
#endif // EMSCRIPTEN
}
@@ -1048,8 +1037,7 @@ void PIEthernet::setType(Type t, bool reopen) {
bool PIEthernet::connectTCP() {
#ifdef EMSCRIPTEN
return false;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
::connect(sock, (sockaddr *)&(PRIVATE->addr_), sizeof(PRIVATE->addr_));
// piCout << errorString();
# ifdef WINDOWS
@@ -1071,7 +1059,7 @@ bool PIEthernet::connectTCP() {
}
# endif
return false;
#endif
#endif // EMSCRIPTEN
}
@@ -1109,13 +1097,12 @@ bool PIEthernet::configureDevice(const void * e_main, const void * e_parent) {
void PIEthernet::propertyChanged(const char * name) {
#ifdef EMSCRIPTEN
return;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
PIConstChars pn(name);
if (pn.endsWith("Timeout")) applyTimeouts();
if (pn == "TTL") applyOptInt(IPPROTO_IP, IP_TTL, TTL());
if (pn == "MulticastTTL") applyOptInt(IPPROTO_IP, IP_MULTICAST_TTL, multicastTTL());
#endif
#endif // EMSCRIPTEN
}
@@ -1204,13 +1191,13 @@ void PIEthernet::configureFromVariantDevice(const PIPropertyStorage & d) {
PIEthernet::InterfaceList PIEthernet::interfaces() {
#ifdef EMSCRIPTEN
return {};
#endif
#else // EMSCRIPTEN
// piCout << "PIEthernet::interfaces()";
PIEthernet::InterfaceList il;
Interface ci;
ci.index = -1;
ci.mtu = 1500;
#ifdef WINDOWS
ci.index = -1;
ci.mtu = 1500;
# ifdef WINDOWS
int ret = 0;
ulong ulOutBufLen = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO pAdapterInfo = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO));
@@ -1261,10 +1248,10 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
}
}
if (pAdapterInfo) HeapFree(GetProcessHeap(), 0, pAdapterInfo);
#elif !defined(EMSCRIPTEN)
# ifdef MICRO_PIP
# else
# ifdef ANDROID
# else // WINDOWS
# ifdef MICRO_PIP
# else
# ifdef ANDROID
struct ifconf ifc;
int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (s == -1) {
@@ -1301,7 +1288,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
}
delete[] ifc.ifc_buf;
::close(s);
# else
# else
struct ifaddrs *ret, *cif = 0;
int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (getifaddrs(&ret) == 0) {
@@ -1319,8 +1306,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ci.address = getSockAddr(cif->ifa_addr);
ci.netmask = getSockAddr(cif->ifa_netmask);
ci.mac.clear();
# ifdef QNX
# ifndef BLACKBERRY
# ifdef QNX
# ifndef BLACKBERRY
int fd = ::open((PIString("/dev/io-net/") + ci.name).dataAscii(), O_RDONLY);
if (fd >= 0) {
nic_config_t nic;
@@ -1328,9 +1315,9 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
::close(fd);
ci.mac = macFromBytes(PIByteArray(nic.permanent_address, 6));
}
# endif
# else
# ifdef MAC_OS
# endif
# else
# ifdef MAC_OS
PIString req = PISystemInfo::instance()->ifconfigPath + " " + ci.name + " | grep ether";
FILE * fp = popen(req.dataAscii(), "r");
if (fp != 0) {
@@ -1341,7 +1328,7 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
}
pclose(fp);
}
# else
# else
if (s != -1) {
struct ifreq ir;
memset(&ir, 0, sizeof(ir));
@@ -1353,8 +1340,8 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
ci.mtu = ir.ifr_mtu;
}
}
# endif
# endif
# endif
ci.flags = 0;
if (cif->ifa_flags & IFF_UP) ci.flags |= PIEthernet::ifActive;
if (cif->ifa_flags & IFF_RUNNING) ci.flags |= PIEthernet::ifRunning;
@@ -1375,10 +1362,11 @@ PIEthernet::InterfaceList PIEthernet::interfaces() {
piCout << "[PIEthernet]"
<< "Can`t get interfaces: %1"_tr("PIEthernet").arg(errorString());
if (s != -1) ::close(s);
# endif
# endif
# endif
#endif
# endif // WINDOWS
return il;
#endif // EMSCRIPTEN
}
@@ -1397,7 +1385,7 @@ PINetworkAddress PIEthernet::interfaceAddress(const PIString & interface_) {
}
struct sockaddr_in * sa = (struct sockaddr_in *)&ifr.ifr_addr;
return PINetworkAddress(uint(sa->sin_addr.s_addr));
#endif
#endif // WINDOWS, MICRO_PIP, EMSCRIPTEN
}
@@ -1422,11 +1410,13 @@ PIVector<PINetworkAddress> PIEthernet::allAddresses() {
int PIEthernet::ethErrorCore() {
#ifdef WINDOWS
return WSAGetLastError();
#elif !defined(EMSCRIPTEN)
return errno;
#else
#else // WINDOWS
# ifdef EMSCRIPTEN
return -1;
#endif
# else // EMSCRIPTEN
return errno;
# endif // EMSCRIPTEN
#endif // WINDOWS
}
@@ -1448,11 +1438,13 @@ PIString PIEthernet::ethErrorString() {
} else
ret += '?';
return ret;
#elif !defined(EMSCRIPTEN)
return errorString();
#else
#else // WINDOWS
# ifdef EMSCRIPTEN
return PIString();
#endif
# else // EMSCRIPTEN
return errorString();
# endif // EMSCRIPTEN
#endif // WINDOWS
}
@@ -1460,8 +1452,7 @@ int PIEthernet::ethRecv(int sock, void * buf, int size, int flags) {
if (sock < 0) return -1;
#ifdef EMSCRIPTEN
return -1;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
return recv(sock,
# ifdef WINDOWS
(char *)
@@ -1469,7 +1460,7 @@ int PIEthernet::ethRecv(int sock, void * buf, int size, int flags) {
buf,
size,
flags);
#endif
#endif // EMSCRIPTEN
}
@@ -1477,8 +1468,7 @@ int PIEthernet::ethRecvfrom(int sock, void * buf, int size, int flags, sockaddr
if (sock < 0) return -1;
#ifdef EMSCRIPTEN
return -1;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
# ifdef QNX
return recv(sock, buf, size, flags);
# else
@@ -1493,7 +1483,7 @@ int PIEthernet::ethRecvfrom(int sock, void * buf, int size, int flags, sockaddr
addr,
&len);
# endif
#endif
#endif // EMSCRIPTEN
}
@@ -1501,8 +1491,7 @@ int PIEthernet::ethSendto(int sock, const void * buf, int size, int flags, socka
if (sock < 0) return -1;
#ifdef EMSCRIPTEN
return -1;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
return sendto(sock,
# ifdef WINDOWS
(const char *)
@@ -1512,15 +1501,14 @@ int PIEthernet::ethSendto(int sock, const void * buf, int size, int flags, socka
flags,
addr,
addr_len);
#endif
#endif // EMSCRIPTEN
}
void PIEthernet::ethClosesocket(int sock, bool shutdown) {
#ifdef EMSCRIPTEN
return;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
// piCout << "close socket" << sock << shutdown;
if (sock < 0) return;
if (shutdown)
@@ -1532,7 +1520,7 @@ void PIEthernet::ethClosesocket(int sock, bool shutdown) {
SHUT_RDWR);
::close(sock);
# endif
#endif
#endif // EMSCRIPTEN
}
@@ -1540,8 +1528,7 @@ int PIEthernet::ethSetsockopt(int sock, int level, int optname, const void * opt
if (sock < 0) return -1;
#ifdef EMSCRIPTEN
return -1;
#endif
#ifndef EMSCRIPTEN
#else // EMSCRIPTEN
auto ret = setsockopt(sock,
level,
optname,
@@ -1552,7 +1539,7 @@ int PIEthernet::ethSetsockopt(int sock, int level, int optname, const void * opt
optlen);
if (ret != 0) piCout << "setsockopt error:" << ethErrorString();
return ret;
#endif
#endif // EMSCRIPTEN
}
@@ -1585,16 +1572,19 @@ void PIEthernet::ethNonblocking(int sock) {
#ifdef WINDOWS
u_long mode = 1;
ioctlsocket(sock, FIONBIO, &mode);
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
fcntl(sock, F_SETFL, O_NONBLOCK);
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
}
bool PIEthernet::ethIsWriteable(int sock) {
#ifdef EMSCRIPTEN
return false;
#endif
#else // EMSCRIPTEN
/* fd_set fd_test;
FD_ZERO(&fd_test);
FD_SET(sock, &fd_test);
@@ -1606,7 +1596,7 @@ bool PIEthernet::ethIsWriteable(int sock) {
timeout.tv_sec = timeout.tv_usec = 0;
::select(fds, nullptr, &fd_test, nullptr, &timeout);
return FD_ISSET(sock, &fd_test);*/
#ifdef WINDOWS
# ifdef WINDOWS
fd_set fd_test;
FD_ZERO(&fd_test);
FD_SET(sock, &fd_test);
@@ -1614,10 +1604,11 @@ bool PIEthernet::ethIsWriteable(int sock) {
timeout.tv_sec = timeout.tv_usec = 0;
::select(0, nullptr, &fd_test, nullptr, &timeout);
return FD_ISSET(sock, &fd_test);
#elif !defined(EMSCRIPTEN)
# else // WINDOWS
int ret = 0;
socklen_t len = sizeof(ret);
getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&ret, &len);
return ret == 0;
#endif
# endif // WINDOWS
#endif // EMSCRIPTEN
}
+77 -48
View File
@@ -91,7 +91,7 @@
# include <fcntl.h>
# include <sys/ioctl.h>
# include <termios.h>
# endif
# endif // EMSCRIPTEN
# ifndef B50
# define B50 0000001
# endif
@@ -176,7 +176,7 @@
#endif
#if defined(LINUX) && !defined(EMSCRIPTEN)
# include <linux/serial.h>
#endif
#endif // LINUX && !EMSCRIPTEN
//! \class PISerial piserial.h
@@ -218,10 +218,13 @@ PRIVATE_DEFINITION_START(PISerial)
HANDLE hCom = nullptr;
DWORD readed = 0, mask = 0;
OVERLAPPED overlap, overlap_write;
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
termios desc, sdesc;
uint readed = 0;
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
PRIVATE_DEFINITION_END(PISerial)
@@ -398,14 +401,17 @@ bool PISerial::setBreak(bool enabled) {
return true;
}
}
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
if (ioctl(fd, enabled ? TIOCSBRK : TIOCCBRK) < 0) {
piCoutObj << "setBreak error: " << errorString();
return false;
} else {
return true;
}
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
return false;
}
@@ -427,13 +433,16 @@ bool PISerial::setBit(int bit, bool on, const PIString & bname) {
}
return true;
}
# elif !defined(EMSCRIPTEN)
# else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) {
piCoutObj << "setBit" << bname << " error: " << errorString();
return false;
}
return true;
# endif
# endif // EMSCRIPTEN
# endif // WINDOWS
#endif
piCoutObj << "setBit" << bname << " doesn`t implemented, sorry :-(";
return false;
@@ -447,11 +456,14 @@ bool PISerial::isBit(int bit, const PIString & bname) const {
}
#ifndef PISERIAL_NO_PINS
# ifdef WINDOWS
# elif !defined(EMSCRIPTEN)
# else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
int ret = 0;
if (ioctl(fd, TIOCMGET, &ret) < 0) piCoutObj << "isBit" << bname << " error: " << errorString();
return ret & bit;
# endif
# endif // EMSCRIPTEN
# endif // WINDOWS
#endif
piCoutObj << "isBit" << bname << " doesn`t implemented, sorry :-(";
return false;
@@ -461,7 +473,7 @@ bool PISerial::isBit(int bit, const PIString & bname) const {
void PISerial::flush() {
#if !defined(WINDOWS) && !defined(EMSCRIPTEN)
if (fd != -1) tcflush(fd, TCIOFLUSH);
#endif
#endif // WINDOWS && EMSCRIPTEN
}
@@ -752,7 +764,9 @@ bool PISerial::openDevice() {
return false;
}
fd = 0;
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
int om = 0;
switch (mode()) {
case PIIODevice::ReadOnly: om = O_RDONLY; break;
@@ -767,7 +781,8 @@ bool PISerial::openDevice() {
tcgetattr(fd, &PRIVATE->desc);
PRIVATE->sdesc = PRIVATE->desc;
// piCoutObj << "Initialized " << p;
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
applySettings();
PRIVATE->event.create();
#ifdef WINDOWS
@@ -789,10 +804,13 @@ bool PISerial::closeDevice() {
// piCoutObj << "close" <<
CloseHandle(PRIVATE->hCom);
PRIVATE->hCom = 0;
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
tcsetattr(fd, TCSANOW, &PRIVATE->sdesc);
::close(fd);
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
fd = -1;
}
PRIVATE->event.destroy();
@@ -830,7 +848,9 @@ void PISerial::applySettings() {
piCoutObj << "Unable to set comm state for \"%1\""_tr("PISerial").arg(path());
return;
}
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
if (fd == -1) return;
tcgetattr(fd, &PRIVATE->desc);
PRIVATE->desc.c_oflag = PRIVATE->desc.c_lflag = PRIVATE->desc.c_cflag = 0;
@@ -864,7 +884,8 @@ void PISerial::applySettings() {
piCoutObj << "Can`t set attributes for \"%1\""_tr("PISerial").arg(path());
return;
}
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
}
@@ -883,9 +904,12 @@ void PISerial::setTimeouts() {
times.WriteTotalTimeoutConstant = isOptionSet(BlockingWrite) ? 0 : 1;
times.WriteTotalTimeoutMultiplier = 0;
if (SetCommTimeouts(PRIVATE->hCom, &times) == -1) piCoutObj << "Unable to set timeouts for \"" << path() << "\"";
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
fcntl(fd, F_SETFL, isOptionSet(BlockingRead) ? 0 : O_NONBLOCK);
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
}
@@ -934,7 +958,10 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
return -1;
// piCoutObj << "read" << (PRIVATE->readed) << errorString();
return PRIVATE->readed;
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
return -1;
# else // EMSCRIPTEN
if (!canRead()) return -1;
if (isOptionSet(PIIODevice::BlockingRead)) {
if (!PRIVATE->event.wait(fd)) return -1;
@@ -949,9 +976,8 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
}
}
return ret;
#else
return -1;
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
}
@@ -974,12 +1000,14 @@ ssize_t PISerial::writeDevice(const void * data, ssize_t max_size) {
sending = false;
// piCoutObj << "send ok" << dwrote;// << " bytes in " << path();
wrote = (ssize_t)dwrote;
#elif !defined(EMSCRIPTEN)
#else // WINDOWS
# ifdef EMSCRIPTEN
return -1;
# else // EMSCRIPTEN
wrote = ::write(fd, data, max_size);
if (isOptionSet(BlockingWrite)) tcdrain(fd);
#else
return -1;
#endif
# endif // EMSCRIPTEN
#endif // WINDOWS
return wrote;
// piCoutObj << "Error while sending";
}
@@ -1196,10 +1224,10 @@ bool parseID(PIString str, PISerial::DeviceInfo & di) {
PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
#ifdef EMSCRIPTEN
return {};
#endif
#else // EMSCRIPTEN
PIVector<DeviceInfo> ret;
DeviceInfo di;
#ifdef WINDOWS
# ifdef WINDOWS
static const GUID guids[] = {GUID_DEVINTERFACE_MODEM, GUID_DEVINTERFACE_COMPORT};
static const int guids_cnt = sizeof(guids) / sizeof(GUID);
for (int i = 0; i < guids_cnt; ++i) {
@@ -1228,12 +1256,12 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
}
SetupDiDestroyDeviceInfoList(dis);
}
#elif !defined(EMSCRIPTEN)
# ifndef ANDROID
# else // WINDOWS
# ifndef ANDROID
PIStringList prefixes;
# ifdef QNX
# ifdef QNX
prefixes << "ser";
# else
# else
prefixes << "ttyS"
<< "ttyO"
<< "ttyUSB"
@@ -1244,14 +1272,14 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
<< "ttyAMA"
<< "rfcomm"
<< "ircomm";
# ifdef FREE_BSD
# ifdef FREE_BSD
prefixes << "cu";
# endif
# ifdef MAC_OS
# endif
# ifdef MAC_OS
prefixes.clear();
prefixes << "cu."
<< "tty.";
# endif
# endif
PIFile file_prefixes("/proc/tty/drivers", PIIODevice::ReadOnly);
if (file_prefixes.open()) {
PIString fc = PIString::fromAscii(file_prefixes.readAll()), line, cpref;
@@ -1272,18 +1300,18 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
}
prefixes.removeDuplicates();
}
# endif
# endif
PIDir dir("/dev");
PIVector<PIFile::FileInfo> de = dir.entries();
# ifdef LINUX
# ifdef LINUX
char linkbuf[1024];
# endif
# endif
for (const auto & e: de) { // TODO changes in FileInfo
for (const auto & p: prefixes) {
if (e.name().startsWith(p)) {
di = DeviceInfo();
di.path = e.path;
# ifdef LINUX
# ifdef LINUX
ssize_t lsz = readlink(("/sys/class/tty/" + e.name()).dataAscii(), linkbuf, 1024);
if (lsz > 0) {
PIString fpath = "/sys/class/tty/" + PIString(linkbuf, lsz) + "/";
@@ -1299,16 +1327,16 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
if (di.pID > 0) break;
}
}
# endif
# endif
ret << di;
}
}
}
# endif
#endif
# endif
# endif // WINDOWS
if (test) {
for (int i = 0; i < ret.size_s(); ++i) {
#ifdef WINDOWS
# ifdef WINDOWS
void * hComm = CreateFileA(ret[i].path.dataAscii(),
GENERIC_READ,
FILE_SHARE_READ,
@@ -1329,7 +1357,7 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
continue;
}
CloseHandle(hComm);
#elif !defined(EMSCRIPTEN)
# else // WINDOWS
int fd = ::open(ret[i].path.dataAscii(), O_NOCTTY | O_RDONLY);
if (fd == -1) {
ret.remove(i);
@@ -1347,10 +1375,11 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
continue;
}
::close(fd);
#endif
# endif // WINDOWS
}
}
return ret;
#endif // EMSCRIPTEN
}
@@ -1368,5 +1397,5 @@ void PISerial::threadedReadBufferSizeChanged() {
ss.xmit_fifo_size = piMaxi(threadedReadBufferSize(), 4096);
ioctl(fd, TIOCSSERIAL, &ss);
// piCoutObj << "a" << ss.xmit_fifo_size;
#endif
#endif // LINUX && !EMSCRIPTEN
}
+12 -10
View File
@@ -98,10 +98,10 @@ PISharedMemory::~PISharedMemory() {
bool PISharedMemory::openDevice() {
#ifdef EMSCRIPTEN
return false;
#endif
#else // EMSCRIPTEN
close();
// piCoutObj << "try open" << path() << dsize;
#ifdef WINDOWS
# ifdef WINDOWS
PRIVATE->name = ("PIP_SHM_" + path()).toByteArray();
PRIVATE->name.push_back(0);
const char * nm = (const char *)PRIVATE->name.data();
@@ -122,8 +122,8 @@ bool PISharedMemory::openDevice() {
return false;
}
// piCout << PRIVATE->map << PRIVATE->data;
#endif
#ifdef SHM_POSIX
# endif
# ifdef SHM_POSIX
PRIVATE->name = ("/pip_shm_" + path()).toByteArray();
PRIVATE->name.push_back(0);
int fd = shm_open((const char *)PRIVATE->name.data(), O_RDWR, 0777);
@@ -153,8 +153,9 @@ bool PISharedMemory::openDevice() {
return false;
}
// piCoutObj << "opened" << PRIVATE->data;
#endif
# endif
return true;
#endif // EMSCRIPTEN
}
@@ -226,17 +227,18 @@ void PISharedMemory::initPrivate() {
PIByteArray PISharedMemory::readAll() {
#ifdef EMSCRIPTEN
return PIByteArray();
#endif
#else // EMSCRIPTEN
if (dsize <= 0) return PIByteArray();
#ifdef WINDOWS
# ifdef WINDOWS
if (!PRIVATE->data) return PIByteArray();
#endif
#ifdef SHM_POSIX
# endif
# ifdef SHM_POSIX
if (!PRIVATE->data) return PIByteArray();
#endif
# endif
PIByteArray a(dsize);
read(a.data(), a.size_s());
return a;
#endif // EMSCRIPTEN
}
+2 -1
View File
@@ -168,7 +168,8 @@ inline double pow10(const double & e) {return pow (10. , e);}
//! \~english Returns `10` raised to the specified power.
//! \~russian Возвращает `10` в указанной степени.
inline ldouble pow10(const ldouble & e) {return powl(10.L, e);}
#endif
#else //EMSCRIPTEN
#endif //EMSCRIPTEN
// clang-format on
+2 -9
View File
@@ -76,16 +76,10 @@
//! \~\ingroup Core
//! \~\brief
//! \~english Defined for Emscripten/WASM targets.
//! \~russian Определяется для целевых сборок Emscripten/WASM.
//! \~english Defined for Emscripten targets.
//! \~russian Определяется для целевых сборок Emscripten.
# define EMSCRIPTEN
//! \~\ingroup Core
//! \~\brief
//! \~english Defined for WebAssembly targets.
//! \~russian Определяется для целевых сборок WebAssembly.
# define WASM
//! \~\ingroup Core
//! \~\brief
//! \~english Defined for reduced embedded PIP builds.
@@ -170,7 +164,6 @@
#endif
#ifdef __EMSCRIPTEN__
# define EMSCRIPTEN
# define WASM
# ifdef __wasm64__
# define ARCH_BITS_64
# else
+77 -27
View File
@@ -2,7 +2,8 @@
#include "piliterals_string.h"
#include "piliterals_time.h"
#ifndef EMSCRIPTEN
#ifdef EMSCRIPTEN
#else // EMSCRIPTEN
# ifndef WINDOWS
# include "pidir.h"
# include "pifile.h"
@@ -25,7 +26,7 @@ extern "C" {
}
// clang-format on
# endif
#endif
#endif // EMSCRIPTEN
bool PIHIDeviceInfo::match(const PIString & str) const {
@@ -63,15 +64,17 @@ void PIHIDeviceInfo::prepare() {
PICout operator<<(PICout s, const PIHIDeviceInfo & v) {
s.saveAndSetControls(0);
s << "PIHIDeviceInfo(" << v.product << " (" << v.manufacturer << "), " << v.VID << ":" << v.PID << ", " << v.axesAbsoluteCount()
<< " abs axes, " << v.axesRelativeCount() << " rel axes, " << v.buttonsCount() << " buttons)";
s << "PIHIDeviceInfo(" << v.product << " (" << v.manufacturer << "), " << v.VID << ":" << v.PID
<< ", " //<< "path \"" << v.path << "\", "
<< v.axesAbsoluteCount() << " abs axes, " << v.axesRelativeCount() << " rel axes, " << v.buttonsCount() << " buttons)";
s.restoreControls();
return s;
}
PRIVATE_DEFINITION_START(PIHIDevice)
#ifndef EMSCRIPTEN
#ifdef EMSCRIPTEN
#else // EMSCRIPTEN
# ifndef WINDOWS
PIFile file;
bool is_js = false;
@@ -80,7 +83,7 @@ PRIVATE_DEFINITION_START(PIHIDevice)
HANDLE deviceHandle = nullptr;
PHIDP_PREPARSED_DATA preparsed = nullptr;
# endif
#endif
#endif // EMSCRIPTEN
PRIVATE_DEFINITION_END(PIHIDevice)
@@ -91,13 +94,13 @@ PIHIDevice::~PIHIDevice() {
bool PIHIDevice::isOpened() const {
#ifdef EMSCRIPTEN
return false;
#else
#else // EMSCRIPTEN
# ifndef WINDOWS
return PRIVATE->file.isOpened();
# else
return PRIVATE->deviceHandle;
# endif
#endif
#endif // EMSCRIPTEN
}
@@ -110,7 +113,7 @@ bool PIHIDevice::open(const PIHIDeviceInfo & device) {
if (device.isNull()) return false;
#ifdef EMSCRIPTEN
return false;
#else
#else // EMSCRIPTEN
# ifndef WINDOWS
if (!PRIVATE->file.open(di.path, PIIODevice::ReadOnly)) {
piCout << "PIHIDevice::open" << di.path << "error:" << errorString();
@@ -138,7 +141,7 @@ bool PIHIDevice::open(const PIHIDeviceInfo & device) {
}
return true;
# endif
#endif
#endif // EMSCRIPTEN
}
@@ -151,7 +154,7 @@ void PIHIDevice::close() {
stop();
#ifdef EMSCRIPTEN
return;
#else
#else // EMSCRIPTEN
# ifndef WINDOWS
PRIVATE->file.close();
# else
@@ -164,13 +167,16 @@ void PIHIDevice::close() {
PRIVATE->preparsed = nullptr;
}
# endif
#endif
#endif // EMSCRIPTEN
}
void PIHIDevice::start() {
if (!isOpened()) return;
PIThread::start(200_Hz);
#ifndef WINDOWS
#else // WINDOWS
#endif // WINDOWS
}
@@ -188,7 +194,7 @@ void PIHIDevice::stop() {
void PIHIDevice::run() {
#ifdef EMSCRIPTEN
return;
#else
#else // EMSCRIPTEN
Event e;
# ifndef WINDOWS
# pragma pack(push, 1)
@@ -199,10 +205,10 @@ void PIHIDevice::run() {
uint value;
};
struct js_event {
uint time;
short value;
uchar type;
uchar number;
uint time; /* event timestamp in milliseconds */
short value; /* value */
uchar type; /* event type */
uchar number; /* axis/button number */
};
# pragma pack(pop)
if (PRIVATE->is_js) {
@@ -212,15 +218,18 @@ void PIHIDevice::run() {
bool ok = false;
switch (ie.type) {
case 2: {
// piCout << ie.value;
cur_axes[ie.number] = procDeadZone(ie.value / 32767. / 2. + 0.5);
ok = true;
} break;
case 1:
// piCout << ie.code;
cur_buttons[ie.number] = ie.value;
ok = true;
break;
default: break;
}
// piCout << ok << ie.type << ie.code << ie.value;
if (!ok) continue;
}
} else {
@@ -229,7 +238,7 @@ void PIHIDevice::run() {
if (ie.type == 0) continue;
bool ok = false;
switch (ie.type) {
case 2: {
case 2: { // rel axis
auto vi = di.axis_by_dataindex.value(ie.code);
if (vi.isValid()) {
e.type = Event::tAxisMove;
@@ -239,35 +248,41 @@ void PIHIDevice::run() {
}
ok = true;
} break;
case 3: {
case 3: { // abs axis
auto vi = di.axis_by_dataindex.value(ie.code);
float fv = (ie.value - vi.min) / piMaxf(1.f, (float)(vi.max - vi.min));
cur_axes[ie.code] = procDeadZone(fv);
ok = true;
} break;
case 1:
case 1: // button
// piCout << ie.code;
cur_buttons[ie.code] = ie.value;
ok = true;
break;
default: break;
}
// piCout << ok << ie.type << ie.code << ie.value;
if (!ok) continue;
}
}
# else
PRIVATE->buffer.resize(di.input_report_size).fill(0);
DWORD readed = 0;
// piCout << "read" << PRIVATE->deviceHandle << PRIVATE->buffer.size();
HIDP_DATA gdd[256];
ULONG gdd_len = 256;
if (ReadFile(PRIVATE->deviceHandle, PRIVATE->buffer.data(), PRIVATE->buffer.size_s(), &readed, nullptr) != TRUE) return;
// piCout << readed << PRIVATE->buffer.size();
if (readed != PRIVATE->buffer.size()) return;
auto gd = HidP_GetData(HidP_Input, gdd, &gdd_len, PRIVATE->preparsed, (PCHAR)PRIVATE->buffer.data(), PRIVATE->buffer.size_s());
NO_UNUSED(gd);
// piCout << "readed" << PRIVATE->buffer << gdd_len;
auto cbit = cur_buttons.makeIterator();
while (cbit.next())
cbit.value() = 0;
for (ULONG i = 0; i < gdd_len; ++i) {
const auto & cd(gdd[i]);
// piCout << cd.DataIndex << cd.RawValue;
auto vi = di.axis_by_dataindex.value(cd.DataIndex);
if (vi.isValid()) {
if (vi.is_relative) {
@@ -276,14 +291,17 @@ void PIHIDevice::run() {
e.value = static_cast<LONG>(cd.RawValue);
event(e);
} else {
// auto & axis(cur_axes[cd.DataIndex]);
float fv = (cd.RawValue - vi.min) / piMaxf(1.f, (float)(vi.max - vi.min));
cur_axes[vi.data_index] = procDeadZone(fv);
}
// piCout << "axis" << vi.data_index << "->" << cur_axes[vi.data_index];
continue;
}
auto bi = di.button_by_dataindex.value(cd.DataIndex);
if (bi.isValid()) {
cur_buttons[bi.data_index] = 1;
// piCout << "button" << bi.data_index << "-> 1";
continue;
}
}
@@ -310,7 +328,7 @@ void PIHIDevice::run() {
}
}
prev_buttons = cur_buttons;
#endif
#endif // EMSCRIPTEN
}
@@ -331,10 +349,9 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
#ifdef EMSCRIPTEN
(void)try_open;
return ret;
#endif
#endif // EMSCRIPTEN
#ifndef WINDOWS
# ifndef EMSCRIPTEN
#if !defined(WINDOWS) && !defined(EMSCRIPTEN)
auto readFile = [](const PIString & path) {
auto ba = PIFile::readAll(path);
@@ -353,18 +370,23 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
PIDir hid_dir("/sys/bus/hid/devices"_a);
auto hid_devs = hid_dir.entries();
for (const auto & hd: hid_devs) {
// piCout << d.path;
if (!isDir(hd)) continue;
PIDir dir_input(hd.path + "/input"_a);
auto hid_inputs = dir_input.entries();
for (const auto & hd_i: hid_inputs) {
if (!isDir(hd_i)) continue;
// now in /sys/bus/hid/devices/<dev>/input/input<N>
// piCout << hd_i.path;
PIHIDeviceInfo dev;
dev.product = readFile(hd_i.path + "/name"_a);
// piCout << readFile(hd_i.path + "/name"_a);
dev.VID = readFile(hd_i.path + "/id/vendor"_a);
dev.PID = readFile(hd_i.path + "/id/product"_a);
dev.version = readFile(hd_i.path + "/id/version"_a);
dev.manufacturer = readFile(hd_i.path + "/id/manufacturer"_a);
// piCout << dev.product;
dev.input_report_size = 24;
PIDir dir_e(hd_i.path);
PIStringList devs;
@@ -373,6 +395,16 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
if (!d_e.isDir() || d_e.flags[PIFile::FileInfo::Dot] || d_e.flags[PIFile::FileInfo::DotDot]) continue;
devs << d_e.name();
}
/*bool dev_found = false;
for (const auto & d: devs) {
if (d.startsWith("js"_a)) {
dev.path = "/dev/input/"_a + d;
dev_found = true;
break;
}
}
if (!dev_found) {*/
// search for event<N> dir
for (const auto & d: devs) {
if (d.startsWith("event"_a)) {
dev.path = "/dev/input/"_a + d;
@@ -387,12 +419,17 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
if (test_f.isClosed()) continue;
}
// ullong ev = readFile(hd_i.path + "/capabilities/ev"_a).toULLong(16);
auto readAxes = [readFile, checkBit, &hd_i, &dev](const PIString & file, bool is_relative) {
PIVector<PIHIDeviceInfo::AxisInfo> ret;
ullong bits = readFile(hd_i.path + file).toULLong(16);
// piCout<< PICoutManipulators::Bin << abs;
if (bits > 0) {
int fd = ::open(dev.path.dataAscii(), O_RDONLY);
if (fd < 0) {}
if (fd < 0) {
// piCout << "Warning: can`t open" << dev.path << errorString();
}
PIHIDeviceInfo::AxisInfo ai;
ai.is_relative = is_relative;
for (int bit = 0; bit < 64; ++bit) {
@@ -403,6 +440,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
if (ioctl(fd, EVIOCGABS(bit), &abs_info) != -1) {
ai.min = abs_info.minimum;
ai.max = abs_info.maximum;
// piCout << "axis" << bit << abs_info.minimum << abs_info.maximum << abs_info.flat << abs_info.fuzz;
} else {
ai.min = 0;
ai.max = 1024;
@@ -442,6 +480,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
for (const auto * hwp: {"/usr/share/hwdata/usb.ids", "/var/lib/usbutils/usb.ids"}) {
PIFile hwf(hwp, PIIODevice::ReadOnly);
if (hwf.isClosed()) continue;
// piCout << "search" << dev.VID << "in" << hwp;
PIString line;
PIIOTextStream ts(&hwf);
while (!hwf.isEnd()) {
@@ -461,8 +500,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
}
}
# endif
#else
#elif defined(WINDOWS)
GUID guid;
HidD_GetHidGuid(&guid);
@@ -512,12 +550,18 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
continue;
}
// piCout << i << deviceHandle;
PHIDP_PREPARSED_DATA preparsed = nullptr;
if (HidD_GetPreparsedData(deviceHandle, &preparsed) == FALSE) {
piCout << "HidD_GetPreparsedData error:" << errorString();
CloseHandle(deviceHandle);
continue;
}
// auto pp = PIByteArray(preparsed, 64);
// piCout << piChangedEndian(pp.dataAs<ushort>(7)) << piChangedEndian(pp.dataAs<ushort>(8)) <<
// piChangedEndian(pp.dataAs<ushort>(9));
// piCout << pp;
dev.path = deviceInterfaceDetailData->DevicePath;
@@ -575,6 +619,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
else
axes_abs << vi;
}
// piCout << vc.LinkCollection << vc.LinkUsage << vc.LinkUsagePage;
}
dev.axes << axes_abs << axes_rel;
for (int i = 0; i < dev.axes.size_s(); ++i)
@@ -587,6 +632,7 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
for (int i = 0; i < _cnt; ++i) {
const auto & bc(button_caps[i]);
PIHIDeviceInfo::ButtonInfo bi;
// dev.values.append(PIHIDeviceInfo::ValueInfo{value_caps[i].BitSize, value_caps[i].LogicalMin, value_caps[i].LogicalMax});
if (bc.IsRange == 1) {
int count = bc.Range.UsageMax - bc.Range.UsageMin + 1;
int cur_index = bc.Range.DataIndexMin;
@@ -595,12 +641,16 @@ PIVector<PIHIDeviceInfo> PIHIDevice::allDevices(bool try_open) {
bi.data_index = cur_index;
dev.buttons << bi;
++cur_index;
// piCout << b << (start_bit / 8) << (start_bit % 8);
}
} else {
bi.index = dev.buttons.size_s();
bi.data_index = bc.NotRange.DataIndex;
dev.buttons << bi;
// piCout << (bi.bit / 8) << (bi.bit % 8);
}
// piCout << bc.IsRange << bc.Range.UsageMin << bc.Range.UsageMax
// << bc.Range.DataIndexMin << bc.Range.DataIndexMax;
}
HidD_FreePreparsedData(preparsed);
+134 -14
View File
@@ -27,14 +27,109 @@
# endif
//! \class PILibrary pilibrary.h
//! \~\details
//! \~english \section _sec0 Synopsis
//! \~russian \section _sec0 Краткий обзор
//! \~english
//! %PILibrary allow you dynamically load external library and use
//! some methods from it. %PILibrary instance contains library
//! pointer and unload library on destructor, so recommended
//! to use it with \b new creation.
//!
//! Main method of %PILibrary is \a resolve(const char *), which returns
//! \c void* pointer to requested method. One should test it
//! to \c nullptr and convert it in pointer to the required method.
//!
//! In case of C++ libraries it`s very important to use [C-linkage](https://en.cppreference.com/w/cpp/language/language_linkage)
//! of exported methods! You may also need to mark methods for
//! export, e.g. \c __declspec(dllexport). You can include \c <piplugin.h>
//! and use \a PIP_PLUGIN_EXPORT to mark exports with PIP.
//!
//! \~russian
//! %PILibrary позволяет динамически загружать стороннюю библиотеку
//! и использовать оттуда методы. Экземпляр %PILibrary содержит
//! указатель на библиотеку и выгружает её в деструкторе, поэтому
//! рекомендуется создавать её с помощью \b new.
//!
//! Основной метод %PILibrary - это \a resolve(const char *), который возвращает
//! \c void* указатель на запрошенный метод. Необходимо проверить его
//! на \c nullptr и преобразовать в указатель на нужный метод.
//!
//! В случае C++ библиотеки очень важно использовать [C-linkage](https://en.cppreference.com/w/cpp/language/language_linkage)
//! для экспортируемых методов! Также может понадобиться пометить
//! методы на экспорт, например, \c __declspec(dllexport). Можно включить \c <piplugin.h>
//! и использовать \a PIP_PLUGIN_EXPORT, чтобы пометить экспорт с помощью PIP.
//!
//! \~\code
//! extern "C" {
//! __declspec(dllexport) int exportedSum(int,int);
//! __declspec(dllexport) int exportedMul(int,int);
//! }
//! \endcode
//!
//! \~english \section _sec1 Usage
//! \~russian \section _sec1 Использование
//!
//! \~english Library:
//! \~russian Библиотека:
//! \~\code
//! #include <piplugin.h>
//!
//! extern "C" {
//! PIP_PLUGIN_EXPORT int exportedSum(int,int);
//! PIP_PLUGIN_EXPORT int exportedMul(int,int);
//! }
//!
//! int exportedSum(int a, int b) {
//! return a + b;
//! }
//! int exportedMul(int a, int b) {
//! return a * b;
//! }
//! \endcode
//!
//! \~english Program:
//! \~russian Программа:
//! \~\code
//! int main(int argc, char * argv[]) {
//! typedef int(*MyFunc)(int,int);
//! PILibrary * lib = new PILibrary();
//! if (lib->load("mylib.dll")) {
//! MyFunc fadd = (MyFunc)lib->resolve("exportedSum");
//! MyFunc fmul = (MyFunc)lib->resolve("exportedMul");
//! if (fadd) {
//! int sum = fadd(1, 2);
//! piCout << "sum =" << sum;
//! } else {
//! piCout << "Can`t resolve" << "exportedSum";
//! }
//! if (fmul) {
//! int mul = fadd(10, 20);
//! piCout << "mul =" << mul;
//! } else {
//! piCout << "Can`t resolve" << "exportedMul";
//! }
//! } else {
//! piCout << lib->lastError();
//! }
//! delete lib;
//! }
//!
//! // sum = 3
//! // mul = 30
//! \endcode
//!
PRIVATE_DEFINITION_START(PILibrary)
# ifdef WINDOWS
HMODULE
# elif defined(EMSCRIPTEN)
void *
# else
# else // EMSCRIPTEN
void *
# endif
# endif // EMSCRIPTEN
hLib;
PRIVATE_DEFINITION_END(PILibrary)
@@ -67,9 +162,9 @@ void PILibrary::unload() {
FreeLibrary(PRIVATE->hLib);
# elif defined(EMSCRIPTEN)
PRIVATE->hLib = 0;
# else
# else // EMSCRIPTEN
dlclose(PRIVATE->hLib);
# endif
# endif // EMSCRIPTEN
PRIVATE->hLib = 0;
}
@@ -79,22 +174,47 @@ bool PILibrary::isLoaded() const {
}
//! \~\details
//! \~english
//! Returns exported method with name "symbol" from
//! loaded library. Method have to use [C-linkage](https://en.cppreference.com/w/cpp/language/language_linkage) and
//! marked to export, according to compiler specification.\n
//! C-linkage doesn`t provide information about return type
//! and arguments, so you should manually convert obtained
//! pointer to required method format before call.
//!
//! \~russian
//! Возвращает экспортированный метод с именем "symbol"
//! из загруженной библиотеки. Метод должен иметь [C-linkage](https://en.cppreference.com/w/cpp/language/language_linkage)
//! и помечен для экспорта, согласно спецификации компилятора.\n
//! C-linkage не предоставляет информации о возвращаемом типе
//! и аргументах, поэтому необходимо вручную преобразовать
//! полученный указатель к формату требуемого метода перед вызовом.
//!
//! \~\return
//! \~english
//! \b void* pointer to method or\n
//! \b nullptr if method doesn`t exists or library not loaded
//!
//! \~russian
//! \b void* указатель на метод или\n
//! \b nullptr если метод не существует или библиотека не загружена
void * PILibrary::resolve(const char * symbol) {
if (!isLoaded()) return 0;
# ifdef EMSCRIPTEN
(void)symbol;
liberror = "dlsym not available on Emscripten";
return 0;
# else
# else // EMSCRIPTEN
void * ret;
# ifdef WINDOWS
ret = (void *)GetProcAddress(PRIVATE->hLib, symbol);
# else
# else // WINDOWS
ret = dlsym(PRIVATE->hLib, symbol);
# endif
# endif // WINDOWS
getLastError();
return ret;
# endif
# endif // EMSCRIPTEN
}
@@ -104,15 +224,15 @@ bool PILibrary::loadInternal() {
# ifdef EMSCRIPTEN
liberror = "dlopen not available on Emscripten";
return false;
# else
# else // EMSCRIPTEN
# ifdef WINDOWS
PRIVATE->hLib = LoadLibraryA(libpath.data());
# else
# else // WINDOWS
PRIVATE->hLib = dlopen(libpath.data(), RTLD_LAZY);
# endif
# endif // WINDOWS
getLastError();
return PRIVATE->hLib;
# endif
# endif // EMSCRIPTEN
}
@@ -121,13 +241,13 @@ void PILibrary::getLastError() {
liberror = errorString();
# elif defined(EMSCRIPTEN)
liberror.clear();
# else
# else // EMSCRIPTEN
const char * e = dlerror();
if (e)
liberror = e;
else
liberror.clear();
# endif
# endif // EMSCRIPTEN
}
#endif // MICRO_PIP
+76 -37
View File
@@ -24,16 +24,49 @@
# include "piliterals_bytes.h"
# include "piprocess.h"
# include "pitranslator.h"
# ifndef WINDOWS
# include <csignal>
# include <sys/wait.h>
# include <fcntl.h>
# endif
# ifdef EMSCRIPTEN
# else // EMSCRIPTEN
# ifndef WINDOWS
# include <csignal>
# include <sys/wait.h>
# include <fcntl.h>
# endif
# endif // EMSCRIPTEN
# ifdef MAC_OS
# include <crt_externs.h>
# endif
//! \class PIProcess piprocess.h
//! \~\details
//! \~english
//! This class able to start external executables, watch for them,
//! grab output and exit code.
//!
//! \~russian
//!
//!
//! \~english \section PIProcess_sec0 Synopsis
//! \~russian \section PIProcess_sec0 Краткий обзор
//! \~english
//! External executable can be started with control or fully independent
//! from application.\n
//! Start with control allow you to wait for finish, grab output
//! and terminate it at any time.\n
//! You can change working directory and environment of executable.\n
//!
//! \~russian
//!
//!
//! \~english \section PIProcess_sec1 Usage
//! \~russian \section PIProcess_sec1 Использование
//! \~english
//!
//!
//! \~russian
//!
namespace {
enum PipeDirection {
PipeRead,
@@ -55,8 +88,8 @@ constexpr int StdFileCount = StdLast + 1;
using PipeHandleType = HANDLE;
using SizeType = DWORD;
# elif defined(EMSCRIPTEN)
using PipeHandleType = int;
using SizeType = ssize_t;
using PipeHandleType = int;
# else
using SizeType = ssize_t;
using PipeHandleType = int;
@@ -71,9 +104,6 @@ PIString convertWindowsCmd(PIStringList sl) {
return sl.join(' ');
}
# elif defined(EMSCRIPTEN)
char * const * convertToCharArrays(const PIStringList &) {
return nullptr;
}
# else
char * const * convertToCharArrays(const PIStringList & sl) {
char ** cc = new char *[sl.size() + 1];
@@ -89,6 +119,7 @@ char * const * convertToCharArrays(const PIStringList & sl) {
PRIVATE_DEFINITION_START(PIProcess)
# ifdef WINDOWS
PROCESS_INFORMATION pi;
# elif defined(EMSCRIPTEN)
@@ -120,7 +151,7 @@ PRIVATE_DEFINITION_START(PIProcess)
# ifdef EMSCRIPTEN
(void)pipe_type;
return false;
# else
# else // EMSCRIPTEN
const int pt = pipe_type;
# ifdef WINDOWS
SECURITY_ATTRIBUTES saAttr;
@@ -133,14 +164,15 @@ PRIVATE_DEFINITION_START(PIProcess)
int ret = pipe(pipes[pt]);
return ret != -1;
# endif
# endif
# endif // EMSCRIPTEN
return false;
}
bool createPipes() {
# ifdef EMSCRIPTEN
return false;
# else
# else // EMSCRIPTEN
for (int i = 0; i < StdFileCount; ++i) {
if (grab[i]) {
if (!createPipe(static_cast<StdFile>(i))) {
@@ -158,7 +190,7 @@ PRIVATE_DEFINITION_START(PIProcess)
if (grab[StdErr]) SetHandleInformation(pipes[StdErr][PipeRead], HANDLE_FLAG_INHERIT, 0);
# endif
return true;
# endif
# endif // EMSCRIPTEN
}
@@ -189,8 +221,9 @@ PRIVATE_DEFINITION_START(PIProcess)
PIByteArray readPipe(StdFile pipe_type) {
# ifdef EMSCRIPTEN
(void)pipe_type;
return {};
# else
# else // EMSCRIPTEN
if (!grab[pipe_type]) return {};
constexpr size_t read_buffer_size = 4_KiB;
PIByteArray read_buffer;
@@ -222,14 +255,15 @@ PRIVATE_DEFINITION_START(PIProcess)
}
}
return read_buffer;
# endif
# endif // EMSCRIPTEN
}
bool writePipe(const PIByteArray & data) {
# ifdef EMSCRIPTEN
(void)data;
return false;
# else
# else // EMSCRIPTEN
SizeType sz = 0;
# ifdef WINDOWS
BOOL ok = WriteFile(pipes[StdIn][PipeWrite], data.data(), data.size(), &sz, NULL);
@@ -247,7 +281,7 @@ PRIVATE_DEFINITION_START(PIProcess)
sz = offset;
# endif
return sz == (SizeType)data.size_s();
# endif
# endif // EMSCRIPTEN
}
PRIVATE_DEFINITION_END(PIProcess)
@@ -257,6 +291,9 @@ PIProcess::PIProcess(): PIThread() {
exit_code = -1;
# ifdef WINDOWS
PRIVATE->pi.dwProcessId = 0;
# elif defined(EMSCRIPTEN)
PRIVATE->pid = 0;
PRIVATE->forEachPipe([](PipeHandleType & pipe) { pipe = -1; });
# else
PRIVATE->pid = 0;
PRIVATE->forEachPipe([](PipeHandleType & pipe) { pipe = -1; });
@@ -288,7 +325,7 @@ void PIProcess::startProc(bool detached) {
exec_start = false;
exec_finished = false;
return;
# else
# else // EMSCRIPTEN
const PIString & str = args.front();
if (!detached) execStarted(str);
if (!PRIVATE->createPipes()) return;
@@ -301,16 +338,17 @@ void PIProcess::startProc(bool detached) {
if (PRIVATE->grab[StdErr]) si.hStdError = PRIVATE->pipes[StdErr][PipeWrite];
si.dwFlags |= STARTF_USESTDHANDLES;
const auto cmd = convertWindowsCmd(args);
if (CreateProcessA(0,
(LPSTR)cmd.data(),
0,
0,
true,
detached ? DETACHED_PROCESS : 0,
0,
wd.isEmpty() ? 0 : wd.data(),
&si,
&(PRIVATE->pi))) {
if (CreateProcessA(0, // No module name (use command line)
(LPSTR)cmd.data(), // Command line
0, // Process handle not inheritable
0, // Thread handle not inheritable
true, // Set handle inheritance to FALSE
detached ? DETACHED_PROCESS /*CREATE_NEW_CONSOLE*/ : 0, // Creation flags
0, // Use environment
wd.isEmpty() ? 0 : wd.data(), // Use working directory
&si, // Pointer to STARTUPINFO structure
&(PRIVATE->pi))) // Pointer to PROCESS_INFORMATION structure
{
exec_start = true;
if (!detached) {
WaitForSingleObject(PRIVATE->pi.hProcess, INFINITE);
@@ -352,6 +390,7 @@ void PIProcess::startProc(bool detached) {
PRIVATE->closePipe(StdErr, PipeWrite);
execve(str.data(), largs, lenv);
// normaly execve can't return, if it returns - error occured
piCoutObj << "\"execve" << str << args << "\" error :" << errorString();
exit(127);
} else {
@@ -377,14 +416,14 @@ void PIProcess::startProc(bool detached) {
# endif
if (!detached) execFinished(str, exit_code);
exec_start = false;
# endif
# endif // EMSCRIPTEN
}
void PIProcess::terminate() {
# ifdef EMSCRIPTEN
return;
# else
# else // EMSCRIPTEN
# ifdef WINDOWS
if (exec_start) {
if (!TerminateProcess(PRIVATE->pi.hProcess, 0)) return;
@@ -394,7 +433,7 @@ void PIProcess::terminate() {
if (exec_start) kill(PRIVATE->pid, SIGKILL);
PRIVATE->pid = 0;
# endif
# endif
# endif // EMSCRIPTEN
}
@@ -408,13 +447,13 @@ void PIProcess::execIndependent(const PIString & program, const PIStringList & a
int PIProcess::pID() const {
# ifdef EMSCRIPTEN
return -1;
# else
# else // EMSCRIPTEN
# ifdef WINDOWS
return PRIVATE->pi.dwProcessId;
# else
return PRIVATE->pid;
# endif
# endif
# endif // EMSCRIPTEN
}
@@ -462,20 +501,20 @@ void PIProcess::enableReadStdErr(bool on) {
int PIProcess::currentPID() {
# ifdef EMSCRIPTEN
return -1;
# else
# else // EMSCRIPTEN
# ifdef WINDOWS
return GetCurrentProcessId();
# else
return getpid();
# endif
# endif
# endif // EMSCRIPTEN
}
PIStringList PIProcess::currentEnvironment() {
# ifdef EMSCRIPTEN
return PIStringList();
# else
# else // EMSCRIPTEN
PIStringList l;
int i = 0;
while (environ[i] != 0) {
@@ -483,7 +522,7 @@ PIStringList PIProcess::currentEnvironment() {
++i;
}
return l;
# endif
# endif // EMSCRIPTEN
}
+13 -12
View File
@@ -20,7 +20,8 @@
#include "pisignals.h"
#include "piincludes.h"
#ifndef EMSCRIPTEN
#ifdef EMSCRIPTEN
#else // EMSCRIPTEN
# ifdef BLACKBERRY
# include <signal.h>
# else
@@ -30,7 +31,7 @@
# define SIGUSR1 10
# define SIGUSR2 12
# endif
#endif
#endif // EMSCRIPTEN
PISignals::SignalEvent PISignals::ret_func;
@@ -38,7 +39,7 @@ PISignals::SignalEvent PISignals::ret_func;
void PISignals::grabSignals(PIFlags<PISignals::Signal> signals_) {
#ifdef EMSCRIPTEN
(void)signals_;
#else
#else // EMSCRIPTEN
if (signals_[PISignals::Interrupt]) signal(signalCode(PISignals::Interrupt), PISignals::signal_event);
if (signals_[PISignals::Illegal]) signal(signalCode(PISignals::Illegal), PISignals::signal_event);
if (signals_[PISignals::Abort]) signal(signalCode(PISignals::Abort), PISignals::signal_event);
@@ -62,14 +63,14 @@ void PISignals::grabSignals(PIFlags<PISignals::Signal> signals_) {
if (signals_[PISignals::StopTTYInput]) signal(signalCode(PISignals::StopTTYInput), PISignals::signal_event);
if (signals_[PISignals::StopTTYOutput]) signal(signalCode(PISignals::StopTTYOutput), PISignals::signal_event);
# endif
#endif
#endif // EMSCRIPTEN
}
void PISignals::releaseSignals(PIFlags<Signal> signals_) {
#ifdef EMSCRIPTEN
(void)signals_;
#else
#else // EMSCRIPTEN
if (signals_[PISignals::Interrupt]) signal(signalCode(PISignals::Interrupt), SIG_DFL);
if (signals_[PISignals::Illegal]) signal(signalCode(PISignals::Illegal), SIG_DFL);
if (signals_[PISignals::Abort]) signal(signalCode(PISignals::Abort), SIG_DFL);
@@ -93,16 +94,16 @@ void PISignals::releaseSignals(PIFlags<Signal> signals_) {
if (signals_[PISignals::StopTTYInput]) signal(signalCode(PISignals::StopTTYInput), SIG_DFL);
if (signals_[PISignals::StopTTYOutput]) signal(signalCode(PISignals::StopTTYOutput), SIG_DFL);
# endif
#endif
#endif // EMSCRIPTEN
}
void PISignals::raiseSignal(PISignals::Signal signal) {
#ifdef EMSCRIPTEN
(void)signal;
#else
#else // EMSCRIPTEN
raise(signalCode(signal));
#endif
#endif // EMSCRIPTEN
}
@@ -110,7 +111,7 @@ int PISignals::signalCode(PISignals::Signal signal) {
#ifdef EMSCRIPTEN
(void)signal;
return 0;
#else
#else // EMSCRIPTEN
switch (signal) {
case PISignals::Interrupt: return SIGINT;
case PISignals::Illegal: return SIGILL;
@@ -138,7 +139,7 @@ int PISignals::signalCode(PISignals::Signal signal) {
default: break;
}
return 0;
#endif
#endif // EMSCRIPTEN
}
@@ -146,7 +147,7 @@ PISignals::Signal PISignals::signalFromCode(int signal) {
#ifdef EMSCRIPTEN
(void)signal;
return PISignals::Termination;
#else
#else // EMSCRIPTEN
switch (signal) {
case SIGINT: return PISignals::Interrupt;
case SIGILL: return PISignals::Illegal;
@@ -174,7 +175,7 @@ PISignals::Signal PISignals::signalFromCode(int signal) {
default: break;
}
return PISignals::Termination;
#endif
#endif // EMSCRIPTEN
}
+12 -7
View File
@@ -47,7 +47,7 @@ PISystemInfo * PISystemInfo::instance() {
ret.hostname = "wasm";
ret.user = "browser";
ret.processorsCount = 1;
#endif
#endif // EMSCRIPTEN
}
return &ret;
}
@@ -66,7 +66,7 @@ PIStringList PISystemInfo::mountRoots() {
} else
clet += PIChar(letters[i]);
}
#else
#else // WINDOWS
# ifdef LINUX
PIString s_df, s_m;
char in[1024];
@@ -87,7 +87,7 @@ PIStringList PISystemInfo::mountRoots() {
}
# else
# endif
#endif
#endif // WINDOWS
return ret;
}
@@ -146,6 +146,7 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
PIString s_df, s_m;
char in[1024];
piZeroMemory(in, 1024);
// piCout << "mountInfo 0";
FILE * fp = popen("df -B1", "r");
PIStringList l_df;
PIMap<PIString, String3> fs;
@@ -155,6 +156,7 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
pclose(fp);
fp = 0;
}
// piCout << "mountInfo 1";
piZeroMemory(in, 1024);
fp = popen("mount -l", "r");
PIStringList tl;
@@ -182,6 +184,7 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
me.label.cutLeft(1).cutRight(1);
}
fs[dev] = me;
// piCout << fsmp << fstl;
}
pclose(fp);
fp = 0;
@@ -201,6 +204,7 @@ PIVector<PISystemInfo::MountInfo> PISystemInfo::mountInfo(bool ignore_cache) {
m.mount_point = s3.mp;
m.label = s3.label;
ret << m;
// piCout << ml;
}
#endif
@@ -224,9 +228,9 @@ PIString confDir() {
""
#elif defined(EMSCRIPTEN)
""
#else
#else // EMSCRIPTEN
PIDir::home().path() + "/.config"
#endif
#endif // EMSCRIPTEN
;
}
@@ -250,14 +254,14 @@ PIString PISystemInfo::machineKey() {
PIString conf = confDir() + "/.pip_machine_salt";
#ifdef EMSCRIPTEN
ret = si->OS_name + "_" + si->architecture;
#else
#else // EMSCRIPTEN
if (PIFile::isExists(conf)) salt = PIFile::readAll(conf);
if (salt.size_s() != SALT_SIZE) {
salt = generateSalt();
PIFile::writeAll(conf, salt);
}
ret = si->OS_name + "_" + si->architecture + "_" + si->hostname + "_" + salt.toHex();
#endif
#endif // EMSCRIPTEN
}
return ret;
}
@@ -268,6 +272,7 @@ uint PISystemInfo::machineID() {
if (ret == 0) {
CRC_32 crc = standardCRC_32();
ret = crc.calculate(machineKey().toByteArray());
// piCout << "machineID \"" << machineKey() << "\" =" << PICoutManipulators::Hex << ret;
}
return ret;
}
+2 -2
View File
@@ -49,7 +49,7 @@
#elif defined(EMSCRIPTEN)
# include <stdint.h>
# define gettid() (pid_t)(uintptr_t) pthread_self()
#endif
#endif //EMSCRIPTEN
#if defined(MAC_OS) || defined(BLACKBERRY)
# include <pthread.h>
#endif
@@ -870,7 +870,7 @@ void PIThread::_beginThread() {
#endif
#if defined(LINUX) || defined(EMSCRIPTEN)
tid_ = gettid();
#endif
#endif //EMSCRIPTEN
setPriority(priority_);
setThreadName();
PIINTROSPECTION_THREAD_START(this);