cpp常用功能

编译器检测CPU框架

1
2
3
4
5
#if defined(__x86__) || defined(__x86_64__)
std::cout << "x86 arch used" << std::endl;
#elif defined(__arm__) || defined(__aarch64__)
std::cout << "arm arch used" << std::endl;
#endif

lambda处理vector求和

1
2
3
4
std::vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };
int sum = 0;
std::for_each(numbers.begin(), numbers.end(), [&sum] (const int& i) { sum += i;});
cout<<sum<<endl;

计算机支持的并发线程数

std::thread标准库中提供了hardware_concurrency()函数,该函数返回当前计算机支持的并发线程数,通常是cpu核数,如果值无法计算则返回0。

1
auto num = std::thread::hardware_concurrency();

std::future

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void A::test(const int val)
{
usleep(val * 1000);
}

void A::testAsync(const int val)
{
static std::future<void> wAsync;
if (wAsync.valid() && wAsync.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout)
{
return;
}
wAsync = std::async(std::launch::async, &SmBuzzer::test, this, val);
}

字符串split

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::vector<std::string> split(const std::string &strtem, const char a)
{
std::vector<std::string> strvec;

std::string::size_type pos1, pos2;
pos2 = strtem.find(a);
pos1 = 0;
while (std::string::npos != pos2)
{
strvec.push_back(strtem.substr(pos1, pos2 - pos1));
pos1 = pos2 + 1;
pos2 = strtem.find(a, pos1);
}
strvec.push_back(strtem.substr(pos1));
return strvec;
}

数组转换成固定长度的字符串

1
2
3
char ss[10];
int i = 6;
sprintf(ss, "%04d", i); // 0006

数字转固定长度字符串

1
2
3
int n_zero = 4; // all count
string number = "2";
std::string str = std::string(n_zero - number.length(), '0') + number;

std::vector释放

std::vector的clear和earse并不会释放对应的空间,只有在退出变量的生命周期时会释放,可使用如下方式释放:

1
2
3
4
{
std::vecotr<T> empty;
a.swap(empty);
}

数值最大值

1
2
3
4
5
#include <iostream>

int max1 = std::numeric_limits<int32_t>::max();
int max2 = INT_MAX;
// max1 == max2;

std::unorder_map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <unorder_map>

struct PairHash {
template <class T1, class T2>
std::size_t operator()(const std::pair<T1, T2> &p) const {
auto h1 = std::hash<T1>{}(p.first);
auto h2 = std::hash<T2>{}(p.second);

// Mainly for demonstration purposes, i.e. works but is overly simple
// In the real world, use sth. like boost.hash_combine
return h1 ^ h2;
}
};

std::unordered_map<std::pair<std::string, uint64_t>, std::unordered_map<std::string, std::vector<Type>>, PairHash> kv;

linux64虚拟地址转换物理地址

来源:https://blog.51cto.com/u_15315240/5108864
cat /proc/[pid]/maps查看进程的虚拟内存地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>

size_t virtual_to_physical(pid_t pid, size_t addr)
{
char str[20];
sprintf(str, "/proc/%u/pagemap", pid);
int fd = open(str, O_RDONLY);
if(fd < 0)
{
printf("open %s failed!\n", str);
return 0;
}
size_t pagesize = getpagesize();
size_t offset = (addr / pagesize) * sizeof(uint64_t);
if(lseek(fd, offset, SEEK_SET) < 0)
{
printf("lseek() failed!\n");
close(fd);
return 0;
}
uint64_t info;
if(read(fd, &info, sizeof(uint64_t)) != sizeof(uint64_t))
{
printf("read() failed!\n");
close(fd);
return 0;
}
if((info & (((uint64_t)1) << 63)) == 0)
{
printf("page is not present!\n");
close(fd);
return 0;
}
size_t frame = info & ((((uint64_t)1) << 55) - 1);
size_t phy = frame * pagesize + addr % pagesize;
close(fd);
printf("The phy frame is 0x%zx\n", frame);
printf("The phy addr is 0x%zx\n", phy);
return phy;
}

int main(void)
{
while(1)
{
uint32_t pid;
uint64_t virtual_addr;
printf("Please input the pid in dec:");
scanf("%u", &pid);
printf("Please input the virtual address in hex:");
scanf("%zx", &virtual_addr);
printf("pid = %u and virtual addr = 0x%zx\n", pid, virtual_addr);
virtual_to_physical(pid, virtual_addr);
}
return 0;
}

linux signal

1
2
3
4
5
6
7
8
9
static void SigHandle(int sig) {
// thread stop and so on
std::this_thread::sleep_for(std::chrono::seconds(3));
exit(0);
}

void main() {
signal(SIGINT, SigHandle);
}

windows读取共享内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 读取共享内存到std::string
std::string readDataFromMem(const std::string &key)
{
HANDLE file = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, key.data());
if (!file)
{
return std::string();
}
LPVOID lpBase = MapViewOfFile(file, FILE_MAP_ALL_ACCESS, 0, 0, 0);

char buffer[INT_MAX / 2] = {0};
strcpy_s(buffer, (char *)lpBase);

UnmapViewOfFile(lpBase);
CloseHandle(file);

std::string data(buffer);
return std::move(data);
}
  1. 读取共享内存,转图像数据。数据为encode后的图像格式数据,以字符串读取,再decode:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cv::Mat readFromMem(std::string key)
    {
    auto data = readDataFromMem(key);
    if (data.empty())
    {
    return cv::Mat();
    }
    cv::Mat img = cv::Mat(1, (int)data.size(), CV_8U, (char *)data.data());
    return cv::imdecode(img, cv::IMREAD_UNCHANGED);
    }
  2. 如果内存中存的是cv::Mat().data图像数据,则使用以下转换:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    bool readMatFromMem(const std::string &key, int64_t size, cv::Mat &dst)
    {
    if (dst.empty())
    {
    return false;
    }
    HANDLE file = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, key.data());
    if (!file)
    {
    return false;
    }
    LPVOID lpBase = MapViewOfFile(file, FILE_MAP_ALL_ACCESS, 0, 0, 0);

    memcpy(dst.data, (void *)lpBase, size);
    UnmapViewOfFile(lpBase);
    CloseHandle(file);
    return true;
    }

    // example
    auto image = cv::Mat::zeros(rows, cols, type);
    readMatFromMem(key, size, image);

windows控制台程序鼠标事件不阻塞程序运行。。

windows控制台程序,双击运行后,防止鼠标时间阻塞程序运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void disableMouseInCmd()
{
// 禁用控制台的鼠标事件
// 获取控制台输入句柄
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
// 获取当前输入模式
DWORD dwInputMode = 0;
GetConsoleMode(hInput, &dwInputMode);
// 设置输入模式为ENABLE_PROCESSED_INPUT
dwInputMode &= ~ENABLE_QUICK_EDIT_MODE;
dwInputMode &= ~ENABLE_MOUSE_INPUT;
dwInputMode &= ~ENABLE_WINDOW_INPUT;
dwInputMode |= ENABLE_PROCESSED_INPUT;
SetConsoleMode(hInput, dwInputMode);
}