Skip to content

Commit 89a9d8b

Browse files
committed
init
1 parent d833f5e commit 89a9d8b

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed

.github/workflows/build.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Build DLL
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
workflow_dispatch:
9+
10+
jobs:
11+
build:
12+
runs-on: windows-latest
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Install MinGW
18+
run: choco install mingw
19+
20+
- name: Compile DLL
21+
run: |
22+
mkdir -p ./build/win32
23+
g++ -shared -o ./build/main.dll ./src/main.cpp
24+
25+
- name: Upload DLL artifact
26+
uses: actions/upload-artifact@v4
27+
with:
28+
name: system_tray
29+
path: build/**/*.dll

src/main.cpp

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#include <windows.h>
2+
#include <string>
3+
#include <stdexcept>
4+
#include <vector>
5+
6+
class SerialPort {
7+
private:
8+
HANDLE hSerial;
9+
OVERLAPPED readOverlap;
10+
OVERLAPPED writeOverlap;
11+
12+
public:
13+
SerialPort() : hSerial(INVALID_HANDLE_VALUE) {
14+
ZeroMemory(&readOverlap, sizeof(OVERLAPPED));
15+
ZeroMemory(&writeOverlap, sizeof(OVERLAPPED));
16+
readOverlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
17+
writeOverlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
18+
}
19+
20+
~SerialPort() {
21+
if (hSerial != INVALID_HANDLE_VALUE) {
22+
CloseHandle(hSerial);
23+
}
24+
if (readOverlap.hEvent) CloseHandle(readOverlap.hEvent);
25+
if (writeOverlap.hEvent) CloseHandle(writeOverlap.hEvent);
26+
}
27+
28+
bool open(const char* portName, DWORD baudRate) {
29+
std::string port = "\\\\.\\";
30+
port += portName;
31+
32+
hSerial = CreateFileA(port.c_str(),
33+
GENERIC_READ | GENERIC_WRITE,
34+
0,
35+
NULL,
36+
OPEN_EXISTING,
37+
FILE_FLAG_OVERLAPPED,
38+
NULL);
39+
40+
if (hSerial == INVALID_HANDLE_VALUE) {
41+
return false;
42+
}
43+
44+
DCB dcbSerialParams = { 0 };
45+
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
46+
47+
if (!GetCommState(hSerial, &dcbSerialParams)) {
48+
CloseHandle(hSerial);
49+
hSerial = INVALID_HANDLE_VALUE;
50+
return false;
51+
}
52+
53+
dcbSerialParams.BaudRate = baudRate;
54+
dcbSerialParams.ByteSize = 8;
55+
dcbSerialParams.StopBits = ONESTOPBIT;
56+
dcbSerialParams.Parity = NOPARITY;
57+
58+
if (!SetCommState(hSerial, &dcbSerialParams)) {
59+
CloseHandle(hSerial);
60+
hSerial = INVALID_HANDLE_VALUE;
61+
return false;
62+
}
63+
64+
COMMTIMEOUTS timeouts = { 0 };
65+
timeouts.ReadIntervalTimeout = MAXDWORD;
66+
timeouts.ReadTotalTimeoutMultiplier = 0;
67+
timeouts.ReadTotalTimeoutConstant = 0;
68+
timeouts.WriteTotalTimeoutMultiplier = 0;
69+
timeouts.WriteTotalTimeoutConstant = 0;
70+
71+
if (!SetCommTimeouts(hSerial, &timeouts)) {
72+
CloseHandle(hSerial);
73+
hSerial = INVALID_HANDLE_VALUE;
74+
return false;
75+
}
76+
77+
return true;
78+
}
79+
80+
bool close() {
81+
if (hSerial != INVALID_HANDLE_VALUE) {
82+
CloseHandle(hSerial);
83+
hSerial = INVALID_HANDLE_VALUE;
84+
return true;
85+
}
86+
return false;
87+
}
88+
89+
DWORD readAsync(BYTE* buffer, DWORD bufferSize) {
90+
if (hSerial == INVALID_HANDLE_VALUE) {
91+
return 0;
92+
}
93+
94+
DWORD bytesRead = 0;
95+
ResetEvent(readOverlap.hEvent);
96+
97+
if (!ReadFile(hSerial, buffer, bufferSize, &bytesRead, &readOverlap)) {
98+
if (GetLastError() == ERROR_IO_PENDING) {
99+
if (WaitForSingleObject(readOverlap.hEvent, INFINITE) == WAIT_OBJECT_0) {
100+
GetOverlappedResult(hSerial, &readOverlap, &bytesRead, FALSE);
101+
}
102+
}
103+
}
104+
return bytesRead;
105+
}
106+
107+
DWORD writeAsync(const BYTE* buffer, DWORD bufferSize) {
108+
if (hSerial == INVALID_HANDLE_VALUE) {
109+
return 0;
110+
}
111+
112+
DWORD bytesWritten = 0;
113+
ResetEvent(writeOverlap.hEvent);
114+
115+
if (!WriteFile(hSerial, buffer, bufferSize, &bytesWritten, &writeOverlap)) {
116+
if (GetLastError() == ERROR_IO_PENDING) {
117+
if (WaitForSingleObject(writeOverlap.hEvent, INFINITE) == WAIT_OBJECT_0) {
118+
GetOverlappedResult(hSerial, &writeOverlap, &bytesWritten, FALSE);
119+
}
120+
}
121+
}
122+
return bytesWritten;
123+
}
124+
};
125+
126+
static SerialPort* port = nullptr;
127+
128+
extern "C" {
129+
__declspec(dllexport) int OpenSerialPort(const char* portName, DWORD baudRate) {
130+
try {
131+
if (port != nullptr) {
132+
delete port;
133+
}
134+
port = new SerialPort();
135+
return port->open(portName, baudRate) ? 1 : 0;
136+
}
137+
catch (...) {
138+
return 0;
139+
}
140+
}
141+
142+
__declspec(dllexport) int CloseSerialPort() {
143+
try {
144+
if (port != nullptr) {
145+
bool result = port->close();
146+
delete port;
147+
port = nullptr;
148+
return result ? 1 : 0;
149+
}
150+
return 0;
151+
}
152+
catch (...) {
153+
return 0;
154+
}
155+
}
156+
157+
__declspec(dllexport) DWORD ReadSerialPort(BYTE* buffer, DWORD bufferSize) {
158+
try {
159+
if (port == nullptr) {
160+
return 0;
161+
}
162+
return port->readAsync(buffer, bufferSize);
163+
}
164+
catch (...) {
165+
return 0;
166+
}
167+
}
168+
169+
__declspec(dllexport) DWORD WriteSerialPort(const BYTE* buffer, DWORD bufferSize) {
170+
try {
171+
if (port == nullptr) {
172+
return 0;
173+
}
174+
return port->writeAsync(buffer, bufferSize);
175+
}
176+
catch (...) {
177+
return 0;
178+
}
179+
}
180+
}
181+
182+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
183+
switch (fdwReason) {
184+
case DLL_PROCESS_ATTACH:
185+
port = nullptr;
186+
break;
187+
case DLL_PROCESS_DETACH:
188+
if (port != nullptr) {
189+
delete port;
190+
port = nullptr;
191+
}
192+
break;
193+
}
194+
return TRUE;
195+
}

0 commit comments

Comments
 (0)