Skip to main content

ciplink

Read and write Allen-Bradley PLC tags over EtherNet/IP from Python, C, C++, C# or Rust.

CI PyPI crates.io NuGet Python License: MIT

Install · Quick start · Simulator · Build from source


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, module identity, and a simulated controller for testing

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);

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.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ciplink 0.3.0
File Size Uploaded Provenance
ciplink-0.3.0.tar.gz 263.5 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for ciplink 0.3.0
File
ciplink-0.3.0-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details
ciplink-0.3.0-cp39-abi3-musllinux_1_2_x86_64.whl CPython 3.9 abi3 Linux musl 1.2+ x86-64 Details
ciplink-0.3.0-cp39-abi3-musllinux_1_2_aarch64.whl CPython 3.9 abi3 Linux musl 1.2+ ARM64 Details
ciplink-0.3.0-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.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details
ciplink-0.3.0-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+ x86-64, macOS 10.12+ universal2 (ARM64, x86-64) Details

Total release size: 7.8 MB

Security for ciplink 0.3.0

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.

Select from 7 files

Attestation for ciplink-0.3.0.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 20, 2026.

Transparency log

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page