ciplink is a fork of pycomm3 rebuilt on a shared Rust core. Every language calls the same driver, so tag reads, packet packing and error handling behave the same everywhere. In Python it keeps the familiar pycomm3-style API and uses several times less CPU per call.
flowchart LR
PY[Python] -->|PyO3| CORE
CPP[C / C++] -->|C ABI| CORE
CS[C# / .NET] -->|P/Invoke| CORE
RS[Rust] --> CORE
CORE[[ciplink core<br/>Rust]] -->|EtherNet/IP| PLC[(Logix · Micro800<br/>SLC · MicroLogix)]
Features
| Controllers | ControlLogix, CompactLogix, GuardLogix and Micro800 with LogixDriver; SLC 500 and MicroLogix with SLCDriver; generic CIP messaging to any EtherNet/IP device with CIPDriver |
| Tag types | atomic types, arrays, strings, UDTs (whole or by member), AOIs, bits of integers and BOOL arrays |
| Throughput | many tags packed into each packet, with large values fragmented and chunked automatically |
| Tag discovery | the tag list and UDT definitions are uploaded on connect, or loaded on first use with lazy_tags; a binary tag cache makes restarts near-instant |
| Online-edit safe | tags are addressed by instance ID and checked against the controller's tag-table version on every read and write, so an online edit never silently returns the wrong tag |
| Extras | tag descriptions, PLC clock, device discovery, RSWho-style device browsing, module identity, and a simulated controller for testing |
| Trends | the controller samples tags at a fixed period (down to 1 ms) and the driver uploads them in batches, like a Studio 5000 trend |
Install
| Language | Command |
|---|---|
| 🐍 Python 3.9+ | pip install ciplink |
| 🦀 Rust | cargo add ciplink |
| 🟣 C# / .NET 8+ | dotnet add package Ciplink |
| ⚙️ C / C++ | ciplink.h, ciplink.hpp and prebuilt libraries on the releases page |
The Python wheels and the NuGet package already contain the compiled core, so you don't need a Rust toolchain.
Quick start
The path is the controller's IP address, IP/slot for a ControlLogix outside slot 0, or a full route such as
192.0.2.10/bp/2/enet/192.0.2.20/bp/0. Every read and write returns one result per tag. A failure is reported on
that result, with a message and an error kind (not found, bad value, access denied and so on), rather than raised
as an exception.
Python
from ciplink import LogixDriver
with LogixDriver("192.0.2.10") as plc:
print(plc.read("Counter")) # Tag(tag='Counter', value=42, type='DINT', error=None)
level, recipe = plc.read("Tank.Level", "Recipe{10}")
plc.write(("Counter", 0), ("Tank.Setpoint", 75.5))
Rust
use ciplink::Value;
use ciplink::logix::driver::{LogixDriver, LogixOptions};
let plc = LogixDriver::new("192.0.2.10", LogixOptions::default())?;
plc.open()?;
for tag in plc.read(&["Counter", "Tank.Level"]) {
println!("{} = {:?} {:?}", tag.tag, tag.value, tag.error);
}
plc.write(&[("Counter", Value::DInt(0))]);
C#
using Ciplink;
using var plc = new LogixDriver("192.0.2.10");
plc.Open();
Tag counter = plc.Read("Counter");
Console.WriteLine(counter.IsOk ? $"{counter.Name} = {counter.Value}" : counter.Error);
plc.Write("Counter", 0);
C++
#include "ciplink.hpp"
ciplink::Logix plc("192.0.2.10");
plc.open();
for (const ciplink::Tag& t : plc.read({"Counter", "Tank.Level"}))
std::cout << t.tag << " = " << ciplink::to_json(t.value) << "\n";
plc.write_tag("Counter", 0);
Trends
For data faster than polling gives, a trend has the controller sample tags every period_ms into its own trend
buffer (the trend object Studio 5000 uses), on a connection of its own. Each sample carries the controller's
timestamp. A pen can be any atomic tag, member or array element of up to 32 bits (BOOL, SINT, INT, DINT, USINT,
UINT, UDINT, REAL) or a bit (Tag.3). 64-bit types (LINT, LREAL) can't be trended. The controller deletes the trend
when it's closed or when its connection drops. Every binding has trends: plc.trend(...) in Python, Rust and C++,
plc.Trend(...) in C#, ciplink_trend_start in C.
import time
from ciplink import LogixDriver
with LogixDriver("192.0.2.10") as plc:
with plc.trend("Motor.Speed", "Tank.Level", "Valve.Open", period_ms=1) as trend:
while trend.running:
time.sleep(0.1)
for sample in trend.read(): # TrendSample(timestamp_us, elapsed_us, values)
print(sample.timestamp, sample.values)
capacity (default 4096) bounds the samples waiting for read(); the oldest are dropped when it is full and
counted in dropped_samples. duration (seconds) stops the trend by itself.
Browse devices
Like RSWho in FactoryTalk Linx: get_ports() lists a device's ports, browse_port() finds the module in each slot,
the node at each address or, on an EtherNet/IP port, every device on the port's subnet. Every node found has a
route to browse further ("" is the device at the IP, "bp/3" the module in slot 3, "bp/2/enet/192.168.1.10" a
device behind the module in slot 2). python -m examples.device_browser is a small tree browser built on them. Every binding has browsing:
get_ports/browse_port/scan_port in Rust, C++ and Python (iter_port streams), GetPorts/BrowsePort/
ScanPort in C#, ciplink_get_ports/ciplink_browse_port/ciplink_scan_port in C.
from ciplink import CIPDriver
with CIPDriver("192.0.2.10") as drv:
for port in drv.get_ports(): # e.g. Backplane, EtherNet/IP
for node in drv.browse_port("", port): # every slot, or every address of the subnet
print(node["route"], node["identity"] and node["identity"]["product_name"])
Test without a PLC
ciplink-sim is a simulated Logix or SLC controller that speaks real EtherNet/IP. Load it with tags and UDTs from
a JSON file or an L5X export, then point any driver at 127.0.0.1.
cargo run -p ciplink-sim -- --config tools/sim/example_controller.json --port 44818
Build from source
You need Rust (stable). The Python package also needs Python 3.9+ with uv, and the C# binding needs the .NET 8+ SDK.
cargo test --workspace # core, simulator, C ABI and the Python ↔ Rust parity harness
uvx maturin build --release # Python wheel, written to target/wheels/
bash bindings/cpp/build_and_test.sh # C++ binding
dotnet test bindings/dotnet # C# binding
See CONTRIBUTING.md for how the parity fixtures are generated and how releases are published.
Project layout
| Path | Contents |
|---|---|
crates/ciplink |
the Rust driver core |
crates/ciplink-py, ciplink/ |
the Python extension module and package |
crates/ciplink-ffi |
the C ABI and ciplink.h |
bindings/cpp, bindings/dotnet |
the C++ and C# bindings |
crates/ciplink-sim |
the simulated controller |
License
MIT. Built on pycomm3 by Ian Ottoway and pycomm by Agostino Ruscito.
Metadata
Release files for ciplink 0.3.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ciplink-0.3.3.tar.gz | 285.7 kB | With provenance | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| ciplink-0.3.3-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| ciplink-0.3.3-cp39-abi3-musllinux_1_2_x86_64.whl | CPython 3.9 | abi3 | Linux musl 1.2+ x86-64 | Details |
| ciplink-0.3.3-cp39-abi3-musllinux_1_2_aarch64.whl | CPython 3.9 | abi3 | Linux musl 1.2+ ARM64 | Details |
| ciplink-0.3.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| ciplink-0.3.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| ciplink-0.3.3-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64 | Details |
Total release size: 8.6 MB
Release files / ciplink-0.3.3.tar.gz
| Download URL | ciplink-0.3.3.tar.gz |
|---|---|
| Size | 285.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6eb60a4fba728f920240fd85dc5314f5d27fbb2da5268434af796eeb42f7f688
|
|
BLAKE2b-256 checksum How to use checksums |
98a324d1f9cf78329196183fc25d38e45d54e4b82c9bd7faed54e3931e1d77a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / ciplink-0.3.3-cp39-abi3-win_amd64.whl
| Download URL | ciplink-0.3.3-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
470b11d96b74ac73d142b8ef7f4eb8f9eac602f8cefa9f5429138e9dcda1f896
|
|
BLAKE2b-256 checksum How to use checksums |
0b47556d5429db6ab84491125c6d944b8720710f25cf8f67c3fb20175ddee67c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / ciplink-0.3.3-cp39-abi3-musllinux_1_2_x86_64.whl
| Download URL | ciplink-0.3.3-cp39-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 1.4 MB |
| Tags | CPython 3.9 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8a1423df2edefa93425aa3bd9938433010464c9ee21a1585aae077030864986c
|
|
BLAKE2b-256 checksum How to use checksums |
0d96e7b23cc3939946c45713c460748cc0d79e7f469dea2f50c3755a3efe2809
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / ciplink-0.3.3-cp39-abi3-musllinux_1_2_aarch64.whl
| Download URL | ciplink-0.3.3-cp39-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.9 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
7f17755fff13e3da27d86a608cd021fb05a9d913ecea9735f0c2cdaf7ea3ecbe
|
|
BLAKE2b-256 checksum How to use checksums |
43dbbbced1eb90744e3affa058e01ed10a97c4cf60c18884e63031e2169af618
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / ciplink-0.3.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | ciplink-0.3.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
b2feb3e780f1c252378f1f1e6597a197df01a949313c3c8b5296b9c5d98ecf5c
|
|
BLAKE2b-256 checksum How to use checksums |
ab57ecb9e5701b3b6d8dff7be32ca8e41fe23625e9adef0ae27f27c9b9cec061
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / ciplink-0.3.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | ciplink-0.3.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 1.2 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
545bfa29536e92cd6c0d54cf1f91ca00a0ebf295d80dcde1f7ad11e846087ef8
|
|
BLAKE2b-256 checksum How to use checksums |
1385b18026a1b3c928d81b90c7e6a676c30b4a3ae3426a2f60f8ea684d5072fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / ciplink-0.3.3-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | ciplink-0.3.3-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 2.1 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1a777965446c490dbdfd49e5783053fa01e4c510630cad0dedfa7101f6feeea6
|
|
BLAKE2b-256 checksum How to use checksums |
4f5f2b49101afb20cc08cc58be65c1021cdd78b94d1820a603cacb4e04945d75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for ciplink 0.3.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 7 files in this release have been uploaded with provenance metadata.
Attestation for ciplink-0.3.3.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.