FreeRDP for Python — the headers, translated 1:1 into ctypes, plus the prebuilt libraries.
pyfreerdpnative is not a hand-written wrapper. Every module in it is generated
from FreeRDP's own C headers: each .h becomes a .py with the same name in the
same folder, carrying that header's #defines, enums, struct layouts and function
prototypes. The wheels bundle the matching FreeRDP libraries, so pip install
gives you a working RDP client and server stack with no system dependencies.
import ctypes
from pyfreerdpnative import load
from pyfreerdpnative.freerdp import freerdp as F, client as CLIENT, settings_keys as KEY
api = load() # opens the bundled libraries,
# binds every prototype
entry = CLIENT.RDP_CLIENT_ENTRY_POINTS_V1()
entry.Size = ctypes.sizeof(entry)
entry.Version = CLIENT.RDP_CLIENT_INTERFACE_VERSION
entry.ContextSize = ctypes.sizeof(F.rdpContext)
ctx = api.freerdp_client_context_new(ctypes.byref(entry))
s = ctx.contents.settings # typed struct access, no offsets
api.freerdp_settings_set_string(s, KEY.FreeRDP_ServerHostname, b"10.0.0.5")
api.freerdp_settings_set_string(s, KEY.FreeRDP_Username, b"alice")
api.freerdp_settings_set_string(s, KEY.FreeRDP_Password, b"secret")
api.freerdp_settings_set_bool(s, KEY.FreeRDP_IgnoreCertificate, True)
if api.freerdp_connect(ctx.contents.instance):
print("connected")
api.freerdp_disconnect(ctx.contents.instance)
api.freerdp_client_context_free(ctx)If you know FreeRDP's C API, you already know this one. The names, argument orders and constants are FreeRDP's; only the syntax is Python.
Wheels are attached to the freerdp-libs-<version> GitHub release. One wheel
per platform, valid for every Python 3.8+ (ctypes never links libpython,
so there is no per-interpreter build):
pip install pyfreerdpnative \
--find-links https://github.com/Usama01TN/PyFreeRdpNative/releases/expanded_assets/freerdp-libs-3.32.1pip picks the wheel for your OS and architecture. Or install a file directly:
pip install https://github.com/Usama01TN/PyFreeRdpNative/releases/download/freerdp-libs-3.32.1/pyfreerdpnative-0.2.0-py3-none-win_amd64.whlEvery build variant is its own pip package. They all provide the same
pyfreerdpnative module, so install exactly one:
| Package | Profile | Media | Contents |
|---|---|---|---|
pyfreerdpnative |
full | FFmpeg + OpenH264 | everything: libraries, all channels, executables (xfreerdp, sfreerdp-server, freerdp-proxy, ffmpeg …) |
pyfreerdpnative-minimal |
minimal | none | libraries only, size-optimised (~4 MB) |
pyfreerdpnative-ffmpeg / -openh264 / -standard |
full | as named | |
pyfreerdpnative-minimal-ffmpeg / -minimal-openh264 / -minimal-media |
minimal | as named |
| Tags | Notes | |
|---|---|---|
| Windows | win_amd64, win32, win_arm64 |
Windows 10+; 32-bit Python needs win32 |
| Linux | manylinux_2_39_*, manylinux_2_34_*, manylinux_2_28_* (x86_64 and aarch64) |
three glibc floors: 2.39, 2.34 and 2.28 - pip picks the highest your system satisfies, covering every supported distribution back to RHEL 8 / Ubuntu 18.04. (glibc 2.17 is not possible: FreeRDP 3.31 needs a C23 compiler and OpenSSL 1.1+.) Alpine/musl is not covered. System libraries are vendored |
| macOS | macosx_11_0_arm64, macosx_11_0_x86_64 |
|
| Android | android_24_arm64_v8a, _armeabi_v7a, _x86_64, _x86 |
PEP 738 tags; installed by cross-install into an app, or retagged for Termux/Pydroid — see docs/MOBILE.md |
| iOS | ios_13_0_arm64_iphoneos, _iphonesimulator |
PEP 730 tags; .dylibs to embed in a signed app bundle — see docs/MOBILE.md |
Windows 7 / 8.1 are not supported by the published wheels (the VS 2022 runtime dropped them); an experimental static-CRT build exists, see scripts/BUILD.md.
pyfreerdpnative/
├── __init__.py load(), FreeRDP, constants, types, functions, PROTOTYPES
├── _loader.py finds _libs, opens the libraries, attaches every prototype
├── _libs/ the FreeRDP libraries (+ executables) for this platform
├── _core/
│ ├── constants.py every #define and enum member, flat
│ ├── types.py every typedef, struct and union as ctypes classes
│ └── functions.py every FREERDP_API / WINPR_API prototype
├── freerdp/ mirror of include/freerdp/ (freerdp.h -> freerdp.py, codec/color.h -> codec/color.py …)
└── winpr/ mirror of winpr/include/winpr/
Use the mirror modules the way you would include headers:
from pyfreerdpnative.freerdp import scancode, input as rdp_input
from pyfreerdpnative.freerdp.codec import color
from pyfreerdpnative.freerdp.gdi import gdi
scancode.RDP_SCANCODE_RETURN # 0x1c from freerdp/scancode.h
rdp_input.KBD_FLAGS_RELEASE # 0x8000 from freerdp/input.h
color.PIXEL_FORMAT_BGRX32 # 0x20040888
gdi.rdpGdi.primary_buffer.offset # 64 — layouts match the C compiler byte for byteEach mirror module also lists the functions its header declares
(freerdp.FUNCTIONS) and can bind just those (freerdp.bind(lib)).
load() returns a FreeRDP object. api.<name> resolves the function in
whichever library exports it, with restype/argtypes from the header:
api.library_of("freerdp_connect") # 'freerdp3'
api.library_of("Stream_New") # 'winpr3'
api.libs["freerdp-client3"] # the raw ctypes.CDLL, if you need it
api.version() # '3.32.1'Because argument types are enforced, passing a plain int where a
POINTER(rdpSettings) is expected raises ctypes.ArgumentError — the C
compiler's type checking, at call time.
Runnable examples ship inside the package, so they work straight from an installed wheel - no repository checkout needed:
pyfreerdpnative-examples # list them
python -m pyfreerdpnative.examples.basic_connect 10.0.0.5 alice secret
python -m pyfreerdpnative.examples --source screenshot # read the codebasic_connect |
connect and disconnect |
send_input |
keyboard and mouse events |
screenshot |
software GDI framebuffer -> BMP |
list_api |
search prototypes and constants, see which library exports what |
diagnose |
find out which layer a failing connection breaks at (DNS, TCP, RDP negotiation, TLS, connect) |
Each is a plain module with a main(argv) function, so it can also be
imported and called, or copied as a starting point:
from pyfreerdpnative.examples import basic_connect
basic_connect.main(["basic_connect", "10.0.0.5", "alice", "secret"])- A high-level Python API. This package deliberately stops at the C API.
Event loops, callbacks (
PostConnect, update handlers, channel callbacks) and rendering are yours to write, exactly as in C.ctypes.CFUNCTYPEtypes for every callback are intypes.py. - A GUI client. The
fullwheels ship FreeRDP's own clients (xfreerdp,wfreerdp,sdl-freerdp) as executables in_libs/; on Linux the SDL client needs the desktop's GTK/WebKit stack. - Loading on a store-installed iOS Python. iOS only loads dylibs from a signed app bundle; see docs/MOBILE.md.
scripts/gen_bindings.py preprocesses the headers with cpp, parses them with
pycparser, and emits Python. It handles the things a naive translation gets
wrong — ALIGN64 fields, #pragma pack, sizeof() in array bounds, ctypes'
array-type caching — and the output is checked against gcc: 767 of 767 struct
sizes match for FreeRDP 3.32.1. CI regenerates the bindings from the pinned
FreeRDP tag on every push and fails if the committed package differs, so
layouts can never drift from the libraries.
pip install pycparser
python scripts/gen_bindings.py \
--include <freerdp>/include --include <freerdp>/winpr/include \
--include <build>/include --include <build>/winpr/include \
--out pyfreerdpnative --version 3.32.1See docs/ARCHITECTURE.md.
scripts/build_freerdp.py builds FreeRDP and its dependencies for every
platform; .github/workflows/build-freerdp.yml runs it across the whole matrix,
generates the bindings from the same checkout, packages the wheels and attaches
everything to a release. scripts/BUILD.md has the details,
including profiles, editions, channel selection and mobile builds.
pip install -e .[dev,generate]
pytest # bindings tests; library tests skip without _libs
PYFREERDP_LIBS=/path/to/_libs pytest # …or point them at a build
ruff check scripts tests pyfreerdpnative/examplesThe package version tracks the Python layer. The FreeRDP version is the
release tag (freerdp-libs-3.32.1) and api.version() at runtime. Struct
layouts are specific to a FreeRDP release: never mix a wheel's pyfreerdpnative
with libraries from a different FreeRDP build.
Apache-2.0 for this project. FreeRDP is Apache-2.0; bundled FFmpeg is LGPL, OpenH264 is BSD (Cisco's binary licence does not apply — it is built from source).