1
0
Fork 0
mirror of https://gitlab.com/niansa/quickipc.git synced 2025-03-06 20:49:18 +01:00

Initial commit

This commit is contained in:
niansa 2021-07-17 20:47:52 +02:00
commit 1dfce00163
3 changed files with 121 additions and 0 deletions

2
Makefile Normal file
View file

@ -0,0 +1,2 @@
install:
cp -r include /usr/include/QIPC

23
examples/main.cpp Normal file
View file

@ -0,0 +1,23 @@
#include "QIPC/ipc.hpp"
#include <iostream>
void child(QIPC& ipc) {
ipc.send("Hello world!");
ipc.send_raw(size_t(1234567890));
}
int main() {
QIPC ipc;
ipc.create();
if (fork() == 0) {
child(ipc);
exit(EXIT_SUCCESS);
}
std::cout << ipc.recv() << std::endl;
std::cout << ipc.recv_raw<size_t>() << std::endl;
}

96
include/ipc.hpp Normal file
View file

@ -0,0 +1,96 @@
#include <string>
#include <string_view>
#include <stdexcept>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
class QIPC {
public:
struct Error : public std::runtime_error {
using std::runtime_error::runtime_error;
};
private:
template<typename T>
static T syscchk(T code) {
if (code < 0) {
throw std::runtime_error(strerror(errno));
}
return code;
}
class Fds {
int raw[2] = {-1, -1};
public:
void create_pipe() {
syscchk(pipe(raw));
}
auto get_in() {
return raw[0];
}
auto get_out() {
return raw[1];
}
} fds;
public:
QIPC(const Fds fds) {
this->fds = fds;
}
QIPC() {}
const Fds& get_fds() {
return fds;
}
void create() {
fds.create_pipe();
}
void send(std::string_view str) {
size_t len = str.size();
syscchk(write(fds.get_out(), &len, sizeof(len))); // Write length
syscchk(write(fds.get_out(), str.data(), len)); // Write data
}
auto recv() {
// Read len
size_t len;
syscchk(read(fds.get_in(), &len, sizeof(len)));
// Check len
if (len > 2000) {
throw Error("Data length limit exceeded");
}
// Read data
auto data = new char[len];
syscchk(read(fds.get_in(), data, len));
// Construct string
auto fres = std::string(data, data+len);
// Clean up
delete []data;
// Return final result
return fres;
}
template<typename T>
void send_raw(const T& data) {
syscchk(write(fds.get_out(), &data, sizeof(data)));
}
template<typename T>
T recv_raw() {
// Disclaimer: Bad practice, but what if T does not have a default constructor?
// This allows us to not construct the object at all!
// Skipping the constructor might even improve performance.
char fres[sizeof(T)];
syscchk(read(fds.get_in(), &fres, sizeof(fres)));
return *reinterpret_cast<T*>(&fres);
}
};