Skip to content

Linux support for the external Python client#2

Open
pskeshu wants to merge 1 commit into
Experimental-Microscopy-Lab:mainfrom
pskeshu:linux-python-bridge
Open

Linux support for the external Python client#2
pskeshu wants to merge 1 commit into
Experimental-Microscopy-Lab:mainfrom
pskeshu:linux-python-bridge

Conversation

@pskeshu

@pskeshu pskeshu commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #1. That PR made the desktop app build and run on Linux; this one
makes the external Python API (ScopeOneCore/python/scopeone) work there too,
so a running ScopeOne can be driven from Python on Linux. Windows behaviour is
unchanged — every platform-specific path is guarded by _WIN32 (C++) or
os.name (Python).

The control protocol (length-prefixed JSON) and the shared-frame layout are
already platform-neutral; only the two transports were Windows-only.

What's in this PR (4 files)

Control channel — src/ScopeOneLocalApiServer.cpp

  • The server name was the literal Windows pipe string, which QLocalServer drops
    verbatim into a socket path on Unix. Made it platform-aware: keep the named
    pipe on Windows, use a plain ScopeOne.Api.local name on Unix (Qt resolves it
    to a unix socket under the temp dir).

Frame export — src/ScopeOneLocalApiServer.cpp / .h

  • On Windows the local-API frame block is a named file mapping
    (CreateFileMapping) that the client opens by name. This adds the Linux
    equivalent: a POSIX shared-memory object (shm_open + mmap) at
    /dev/shm/ScopeOne.Api.frame, cleaned up with munmap/shm_unlink on
    shutdown.

Python client — ScopeOneCore/python/scopeone

  • Split the transport behind one internal interface: Windows keeps the pywin32
    named pipe + mmap(tagname=...); Linux uses an AF_UNIX socket and reads
    frames by mmap-ing the /dev/shm object. The public API, the request
    protocol, and shm.py are unchanged.
  • pyproject.toml: pywin32 is now a Windows-only dependency, and the Linux
    classifier is added.

Verification

Tested end-to-end against the demo camera on Linux (Manjaro, Qt 6.11, Python
3.14):

connect -> load_config -> start_preview -> record(3) -> session.frame("Camera", 0)
=> (512, 512) uint16 numpy array

No extra Python dependencies on Linux — the client uses only the standard
library (socket, mmap).

Scope

  • Demo camera; Windows transports unchanged (guarded, not re-tested on my end —
    a Windows check would be welcome).
  • No other behaviour touched.

The external Python API previously assumed Windows transports (named pipe +
named file mapping). This makes both the client and the server side of the
local API cross-platform, so a running ScopeOne can be driven from Python on
Linux. Windows behaviour is unchanged (guarded by _WIN32 / os.name).

Server (src/ScopeOneLocalApiServer.cpp/.h):
- Platform-aware control endpoint: keep the Windows named pipe, use a plain
  QLocalServer name on Unix (resolves to <tempdir>/ScopeOne.Api.local).
- Frame export on Linux via a POSIX shared-memory object (shm_open + mmap),
  visible to external clients at /dev/shm/ScopeOne.Api.frame; cleaned up with
  munmap/close/shm_unlink on shutdown.
- Frame-export readiness check is platform-specific: the Windows handle+view
  check is left unchanged; Linux checks the mapped view (there is no Windows
  handle there).

Client (ScopeOneCore/python/scopeone):
- Split the transport: Windows keeps the pywin32 pipe + tagname mmap; Unix uses
  an AF_UNIX socket and reads frames by mmapping /dev/shm. Protocol and frame
  layout are identical, so the public API and shm.py are unchanged.
- pyproject: make pywin32 a Windows-only dependency and add the Linux classifier.

Verified on Linux against the demo camera: connect -> load_config -> preview ->
record -> session.frame() returns a (512,512) uint16 numpy array.
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.

1 participant