Skip to content

Add Windows support and native PlatformIO test coverage - #24

Merged
pschatzmann merged 7 commits into
pschatzmann:mainfrom
yanxke:yan/windows-port
Sep 3, 2026
Merged

pschatzmann merged 7 commits into
pschatzmann:mainfrom
yanxke:yan/windows-port

Conversation

@yanxke

@yanxke yanxke commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Windows support to the desktop Arduino emulator while preserving the existing POSIX/Linux implementation. Tested on both Windows and Ubuntu.

Changes

  • Fix RingBufferExt handling of valid 0x00 payload bytes.
  • Add platform detection and cross-platform socket abstractions.
  • Implement Windows Winsock support.
  • Split POSIX and Windows Ethernet server implementations.
  • Make UDP networking cross-platform and correctly handle hostname resolution, non-blocking reads, socket errors, and send/receive loopback traffic.
  • Add Windows serial support, including COM ports 10 and above.
  • Make physical serial devices opt-in when running on Windows.
  • Add Windows-compatible SD directory creation.
  • Add a native PlatformIO example and Unity test suite.

Testing

Verified with:
pio test -e native
All 9 native tests passed, including GPIO delegation, SD filesystem operations, UDP loopback, TCP loopback, socket error mapping, Arduino types, and timing behavior.

@pschatzmann

Copy link
Copy Markdown
Owner

Review of PR #24 found 4 issues, ranked by severity:

  • entry.cpp:20 — Windows WinMain calls setup()/loop() directly, skipping hardwareSetup() that the POSIX path runs via Main.cpp. On Windows builds with USE_RPI/USE_FTDI/USE_REMOTE, hardware peripherals never get initialized.
  • SocketImplWindows.cpp:1184 — getIPAddress(validEntries[]) on Windows ignores the interface filter entirely, always returning the hostname's address instead of matching POSIX's interface-selection behavior.
  • EthernetServerWindows.h:725 — Windows begin_() swallows listen failures silently (no Logger.error), unlike POSIX which logs "listen failed" — makes port-in-use failures hard to diagnose.
    Simplification (1):
  • . Serial.h:36 — The new #if ARDUINO_EMULATOR_WINDOWS/#else branches are identical, dead conditional code that risks silent divergence on future edits.

@yanxke

yanxke commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Review of PR #24 found 4 issues, ranked by severity:

  • entry.cpp:20 — Windows WinMain calls setup()/loop() directly, skipping hardwareSetup() that the POSIX path runs via Main.cpp. On Windows builds with USE_RPI/USE_FTDI/USE_REMOTE, hardware peripherals never get initialized.
  • SocketImplWindows.cpp:1184 — getIPAddress(validEntries[]) on Windows ignores the interface filter entirely, always returning the hostname's address instead of matching POSIX's interface-selection behavior.
  • EthernetServerWindows.h:725 — Windows begin_() swallows listen failures silently (no Logger.error), unlike POSIX which logs "listen failed" — makes port-in-use failures hard to diagnose.
    Simplification (1):
  • . Serial.h:36 — The new #if ARDUINO_EMULATOR_WINDOWS/#else branches are identical, dead conditional code that risks silent divergence on future edits.

All addressed.

@pschatzmann
pschatzmann merged commit 115fe2f into pschatzmann:main Sep 3, 2026
1 check passed
David-Vandensteen pushed a commit to David-Vandensteen/Arduino-Emulator that referenced this pull request Oct 21, 2026
…ortability work

Merges the connect-timeout feature from PR pschatzmann#21 (timeout-aware
EthernetClient/SocketImpl connect(), aligning behavior with ESP32/Pico
Arduino cores) onto main, which had since gained Windows portability
support (PR pschatzmann#24) that PR pschatzmann#21 predates. Conflicts were in Ethernet.h's
connect()/resolveAddress() (both PRs touched the same functions).

Beyond conflict resolution, this adds what PR pschatzmann#21 was missing for the
now-merged Windows target and closes gaps found in review:

- SocketImplWindows.cpp: add the 3-arg connect(address, port,
  timeout_ms) override (nonblocking connect + select()), and fix
  read()'s signature/semantics to match the updated SocketImpl
  contract (int return, -1 on error/EOF, 0 on would-block).
- NetworkClientSecure.h: add the missing 3-arg connect() override on
  SocketImplSecure - without it, EthernetClient::connect() routed
  through the new 3-arg virtual and silently bypassed the TLS
  handshake for every NetworkClientSecure user.
- Ethernet.h: bound hostname resolution by timeout_ms using a
  background thread + future, so connect(host, port, timeout_ms) stays
  bounded even when DNS is slow (getaddrinfo has no timeout of its
  own), deducting the time spent from the budget passed to the
  subsequent TCP connect.
- test/native/test_native.cpp: add deterministic connect-refused and
  connect-timeout tests (the latter POSIX-only, guarded because
  Winsock's behavior on a saturated accept queue isn't verified here).

Verified with the existing native unity suite (11/11 passing,
repeated runs), plus manual runtime checks of TLS connect/handshake,
refused-connection, and timeout paths against a local wolfSSL build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants