Hi all,

currently we’re in a mode of synchronous exchange on creating the PLC4C API on 
Apache slack “the-asf.slack.com” (Please send an email if you need an invite).
We’re doing that as specially in the beginning this simplifies and speeds up 
things drastically.

But as we’re at Apache and here “If it didn’t happen on the list, it didn’t 
happen” I’m trying to keep the list in sync with the outcome and give you folks 
the chance to participate by writing up summaries.

So we have the great situation that Otto and Björn have quite some experience 
in C and C++ and are being a huge help with getting this started.

So a few weeks ago I have already setup a build that’s integrated into our 
normal Maven build. However you need to enable to profiles in order to do that:

  *   with-sandbox
  *   with-c

You need to run the maven build at least once as our plc4x-maven-plugin is a 
maven plugin and we need to have it generate some code first (or the build will 
fail)

The actual build however is done with CMake. This allows us to use any 
CMake-capable IDE to develop PLC4C (I’m using CLion, but VisualStudio seems to 
also work fine).

Today I created a branch feature/c-api as I think I’ll sometimes be committing 
unbildable stuff in order to allow collaboration (I commit something and others 
fix it ;-) ).
So please follow this branch.

Regarding the directory structure, we decided to stick to a structure that is 
sort of aligned with the one we have in PLC4X as this makes it easier to 
understand the structure (at least from a PLC4J point of view). The structure 
should also not be too strange for a c developer. What C developers might 
consider “an abomination” is that I started off using a directory structure for 
modules which is maven-inspired.

The reason is that I think this allows to cleanly separate prod from test code 
and code from resources (In this case code from header files) … so a C module 
currently has the general structure:

CMakeLists.txt
src
- main
- c
- include
- test
- c
- include

The CMakeLists.txt file is sort of the equivalent to our pom.xml … it tells 
CMake how to build the module. This is also where you define “dependencies” … 
however in C you rather define the locations of the header-files you intend on 
using … the actual using of code will happen by the linker when compiling.

So now come the parts where I was super happy to have some help with:

  *   In the API module we have a set of header files which define the core 
functions and types
  *   However these types don’t really expose any information on the internals 
of PLC4X. So even if you have a connection structure, you can’t access any 
properties of this directly. If you want to access any properties, you need to 
use the corresponding function. So if in the “connection” domain you have a 
plc4c_connection structure, in order to access the connection_string property 
of that, you need to call the plc4c_connection_get_connection_string function 
and pass in your connection object.
  *   As a currently implicit naming convention we started using a prefix 
“plc4c_” for everything.
  *   We also split up the API functions into domains like “system”, 
“connection”, … all the functions which then results in names like 
“plc4c_system_create”. As we’re expecting the domains to grow, this way we hope 
to keep the sizes of the code blocks manageable.
  *   While the interface a user would use is defined in the API module, the 
implementation is then done in the SPI module (pretty much like in PLC4J)
  *   Initially we started playing around with callbacks, much like we’re doing 
in Java and as C does allow function pointers, that seemed like a good idea. 
But people actually coding in C mentioned that this form of coding feels very 
strange for full-blooded C developers. As we want this API to feel native for C 
developers, we’ll go down this path.
  *   As C doesn’t support a try-catch-finally style error handling, almost 
every function returns a return_code enum which can be translated into error 
messages by using some helper functions. So it is important to check if an 
operation returned OK and to do some error handling, if this is not OK.
  *   The API will completely not use synchronous operations. So we won’t 
provide a blocking “connect” function that returns as soon as the connection is 
established, as some of the systems we’re going to support are single threaded 
and don’t have any mutlitasking or scheduling. Therefore we’ll have a 
“plc4c_system_loop()” function which is cyclically called in order to do 
something.

So far the update … I hope I didn’t skip anything …

More will follow :-)

Chris

Reply via email to