libplctag: reading and writing PLC tags from C over EtherNet/IP and Modbus TCP
This C library provides a portable and simple API for accessing Allen-Bradley and Modbus PLC data over Ethernet.
At a glance
- What is it?
- libplctag is a portable C library that reads and writes tags in Allen-Bradley and Modbus PLCs over Ethernet, with a deliberately small API that is easy to wrap from other languages. It suits control engineers and integrators who need to talk to a PLC from a Linux box, a Windows service or an embedded target.
- Who is it for?
- libplctag is a good fit for a control engineer who needs a stable, portable C library for PLC tag access, who is working on a platform the vendor libraries do not cover, and who is willing to read a disclaimer that says plainly that mistakes in PLC access can cost property, production or lives. It is the wrong tool for a Windows-only project that can use a vendor SDK, and it is the wrong tool for a non-Allen-Bradley PLC family that libplctag does not speak to.
- Can I use it commercially?
- Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 19 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A C library that has shipped since 2012
The stated purpose is narrow and clear: an open source C library for Linux, Windows and macOS using EtherNet/IP or Modbus TCP to read and write tags in PLCs. The longevity claim is part of the pitch, and the documentation backs it with specifics, saying the library has been in production since early 2012 and is used by multiple organizations for tasks including controlling radio telescopes, large and precision manufacturing, fitness equipment and food handling. The API stability note is the one that matters most for an industrial buyer: a very stable API with almost no changes other than feature additions since 2012. In a control system that must run for a decade, an API that does not move is worth more than a new feature, because it means the integration you write today still compiles next year. The design goal behind the API is stated as well, a simple API with minimal use of language-specific data to enable easy wrapping in other languages, and that is the reason wrappers exist for C#/.Net, Julia and others rather than a first-class binding for each.
The disclaimer is the most important sentence in the README
The documentation puts a warning section near the top, and the wording is unusually direct. It notes that PLCs control many kinds of equipment and that loss of property, production or even life can happen if mistakes in programming or access are made, and that you should always use caution when accessing or programming PLCs. The project then makes no claims or warrants about the suitability of this code for any purpose. That is a legal disclaimer rather than a technical one, but it has a technical consequence worth taking seriously: a tag read is not a side-effect-free operation in the way a database query is. Writing a boolean to the wrong tag on a running machine can move something. A library that gives you a straightforward write path inherits that responsibility, and the disclaimer is there to say the responsibility stays with the integrator. It also tells you what kind of library this is not. It is not a safety instrumented function, it is not a certified control component, and it is not something to put between a safety relay and the machine it protects. The separate SECURITY.md file, added in the v2.7.0 release with private reporting guidance and a response policy, is the other half of how the project treats risk, and the repository also carries an AI-POLICY.md, which is unusual to see in a C library of this age.
What the CIP path can read and write
The PLC support section is the substance of the library, and the Rockwell list is the longest part of it. For ControlLogix PLCs over CIP-EtherNet/IP, the documentation lists read and write of 8, 16, 32 and 64-bit signed and unsigned integers, read and write of single bits and booleans, read and write of 32-bit and 64-bit IEEE little endian floating point, and read and write of arrays of all of those. There is raw support for user-defined structures, with the important caveat that you need to pull out the data piece by piece, which is a fair description of what a struct tag means on a ControlLogix. Two performance-related features sit at the protocol level rather than the API level: multiple-request support per packet, and packet size negotiation with newer firmware, described as version 20 and later, and hardware. There is also tag listing, both controller and program tags, which is the feature you need when you are reverse engineering a tag name. Micro 850 PLCs are supported as far as ControlLogix support allows. The older Rockwell families are supported too, with PLC-5 PLCs on upgraded Ethernet, SLC 500 and MicroLogix over Ethernet via CIP, and for those the read and write types are narrower, 16-bit INT, 32-bit floating point and 32-bit integer on the L data file for MicroLogix.
Getting the code and building it with CMake
The distribution route is deliberately plain. The documentation says to download it from the releases page, and the project is a source library rather than a package with a dependency tree, so what you do next is build it. The repository carries a CMakeLists.txt at the root, a cmake directory with additional modules and a cmake_toolchains directory for cross compilation, and a libplctag.pc.in template, which is the pkg-config input that lets a build system find the installed library and its flags without hand-written paths. A pkg-config file is the small piece of glue that makes the library pleasant to consume from a C project with a Makefile, and having the template in the tree means the install step can generate it correctly. The documentation also points to extensive example programs showing use of all library features, and lists Code, Example Code and API as sections of the guide, so the intended path is to read the examples before reading the reference. For a language other than C, the answer is a wrapper, and the documentation names C#/.Net, Julia and others, with the repository topics also listing Go, Java, Pascal, LabVIEW and C#, which tells you the wrapper ecosystem is a live part of the project rather than a historical footnote.
Twelve tested platform combinations per release
The Tier One platform table is more informative than a generic support statement, because it names exact versions that are fully tested with each release. The list covers Alpine Linux v3.23.0-62 with GCC 15.2.0 on x86-64 and Aarch64, macOS 14 and macOS 15 with Apple-Clang 17.0.0 on x86-64 and Aarch64, Ubuntu Linux 24.04 with GCC 13.3.0 on x86-64, Aarch64 and x86, plus Ubuntu with the musl variant of GCC on x86-64, and Windows 11 with Server 22 using MSVC 19.44.35221.0 on x86-64, x86 and Aarch64, along with Windows 11 under MinGW-GCC 14.2.0 on x86-64. Each row carries a CI badge tied to the release branch, so the table is a live signal rather than a snapshot. Two things are worth reading out of it. The presence of a musl build means the library is expected to run in minimal container images, which matters for edge deployments. And the inclusion of 32-bit x86 on Linux and Windows means the library still supports the older industrial hardware that tends to outlive the software written for it. The high level feature list also claims support for x86, ARM and MIPS and probably others, alongside pure C portability across 32-bit and 64-bit.
Performance claims tied to protocol features, not benchmarks
The performance story in the documentation is a design argument rather than a measurement. The claim is low memory use and very high performance and capacity, and the mechanism given is that it uses protocol-specific features to increase performance. That is a specific and credible statement for this domain, because the obvious alternative to reading one tag is to batch requests, and the multiple-request support per packet and the packet size negotiation features exist precisely so the library can amortise the round trip. The consequence for a user is that a well-formed tag list read in one call is very different from a loop of individual reads, and the library gives you the tools to do the first. There is no benchmark table in the documentation, and the honest reading is that performance is a property you verify against your own PLC and network. The other architectural commitment worth noting is the protocol split. EtherNet/IP and Modbus TCP are separate code paths inside one library with one API, which means a program written against the tag interface can be pointed at either, and it also means the tag naming rules differ between them, which is where integrators spend their time.
Dual licensing under MPL 2.0 or LGPL 2+
The licence is unusual and worth reading carefully. The high level feature list describes the project as open source licensing under the MPL 2.0 or LGPL 2+, and the repository root carries two licence files, LICENSE-1.MPL and LICENSE-2.LGPL, which is the standard arrangement for a dual-licensed library. The practical effect is that you can take it under whichever of the two suits your distribution model. Under the LGPL terms you can link to it and treat it as a library, which is the path most commercial integrators take, and the MPL terms apply if you modify the library itself and require the modified files to stay available. This is a file-level copyleft arrangement rather than a whole-work one, so using the library in a proprietary application does not by itself impose an obligation to publish that application. The choice between the two is a decision for whoever handles licensing in your organisation, and this review does not make it for you. The last push was on 2026-10-04, and the release history shows a project that responds to defects: v2.7.2 on 2026-09-09 with more buffer over and underflow fixes, following v2.7.1 on 2026-08-08 with bug fixes and buffer checks. Two consecutive releases fixing buffer bounds is worth noticing in a library that writes to PLC memory.
Editorial conclusion
libplctag is a good fit for a control engineer who needs a stable, portable C library for PLC tag access, who is working on a platform the vendor libraries do not cover, and who is willing to read a disclaimer that says plainly that mistakes in PLC access can cost property, production or lives. It is the wrong tool for a Windows-only project that can use a vendor SDK, and it is the wrong tool for a non-Allen-Bradley PLC family that libplctag does not speak to. Before adopting it, check which PLC families and firmware versions the documentation lists, and read the API section, because the tag naming conventions differ between the CIP and Modbus paths and that is where integration time goes. The library is licensed under the MPL 2.0 or LGPL 2+, the last push was on 2026-10-04, and the most recent release is v2.7.2 from 2026-09-09.
Frequently asked questions
What protocols and PLCs does libplctag support?
It is a C library that uses EtherNet/IP or Modbus TCP to read and write tags in PLCs. Rockwell and Allen-Bradley ControlLogix PLCs are supported over CIP-EtherNet/IP, along with Micro 850 PLCs, and older Rockwell families such as PLC-5, SLC 500 and MicroLogix with Ethernet via CIP.
How do I get and build libplctag?
The documentation says to download it from the releases page. The library is built with CMake, and the repository includes a CMakeLists.txt, a cmake directory, a cmake_toolchains directory for cross compilation and a libplctag.pc.in template that generates a pkg-config file for the install.
What data types can libplctag read and write?
On ControlLogix over CIP-EtherNet/IP it reads and writes 8, 16, 32 and 64-bit signed and unsigned integers, single bits and booleans, 32-bit and 64-bit little endian IEEE floating point, and arrays of these, plus raw support for user-defined structures where you pull the data out piece by piece. Older Rockwell families support a narrower set.
Which platforms are fully tested for libplctag?
The Tier One table lists the OS and compiler combinations fully tested with each release, including Alpine Linux with GCC, macOS 14 and 15 with Apple-Clang, Ubuntu 24.04 with both GCC and GCC-musl, and Windows 11 with MSVC and MinGW-GCC, on x86, x86-64 and Aarch64. Each row carries a CI badge for the release branch.
What licence is libplctag released under?
It is dual licensed under the MPL 2.0 or LGPL 2+, with both licence files present in the repository root. The most recent release is v2.7.2 from 2026-09-09, which added more buffer over and underflow fixes, and the last push was on 2026-10-04.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/libplctag-libplctag)Was this useful?