-1

We are working on a data logging code and I would like to make a library of it. The only thing that different programs will need to define is the type strict for the sample that the want to save. The library will save a sample every x period. But I don't know exactly how to have an external DTU in the library code? Is possible to declare the DTU as an interface or something similar? There must be a way to do so but not so sure what it is.

user4157124
  • 2,809
  • 13
  • 27
  • 42
homer69
  • 53
  • 1
  • 8
  • Does your data logging code offer a choice between a set of types the external code will choose from, or does your data logging code work on values it treats as raw bytes of data that are logged without knowing what they are? What does "logging" mean to you in this context? A file? A database? Some kind of RPC-like remote logging? – Fred Feb 18 '22 at 13:18
  • This is a series of data built into a struct, the software will add a number of samples of this struct type to an array and then save to file. The data logger doesn't technically need to know what is inside the strict type SAMPLE_DATA but having this defines as a struct in the library code makes things a little easier. Different programs will have a different struct type with the same name. I could indeed use a generic array of bytes and the size of the struct, but is there any way to define an 'opuque' struct in the codesys library which will be overwritten by the program usjng the library? – homer69 Feb 19 '22 at 01:47

1 Answers1

0

CODESYS does not have generics, there is no way around that. Although I am not convinced it would be an elegant or fitting design, there is one way you might be able to do if you really want your type to be visible in your logging library, but it has serious drawbacks.

You can create another library, or more accurately a family of libraries that will all use the same placeholder. Each of these libraries can define a type of the same name. Reference this placeholder from your logging library, so that it will resolve the name. That will allow your library to compile. Then, by controlling which library the placeholder resolves to inside the project, you can select which type is used. The big downside is you cannot use your logging library with two different types inside the same project, as you cannot get a placeholder to resolve to two libraries at the same time.

Personally, I would probably implement the logging library with some sort of log entry writer as a function block that contains size + arrays of bytes and manages the details of actual logging, and then define inherited function blocks in projects/libraries that need logging. Each of these inherited function blocks would give access to the bytes in a typed way (method, exposed reference/pointer) and assign the size based on the data type used (SIZEOF in FB_Init, for instance). This requires a bit of code for each type, but really not much, and new types are easy to add with a 20-second copy+paste+modify.

Fred
  • 6,590
  • 9
  • 20
  • Using placeholders to "fill in the blanks" with implementations that are actually separate has one interesting use case : creating an abstraction layer for mechanisms that differ between environments (e.g. CODESYS, TwinCAT). You create a main library which references a placeholder, one library for each environment that is marked with this placeholder and references the main library, and the placeholder resolves based on which environment it is used in. The reference cycle does not seem to be a problem, and as long as the main library uses types/function/methods that are available, it works. – Fred Feb 20 '22 at 12:01
  • yes this was the same solution I thought about, the only problem is that I am also passing an array of structs from the retain memory to the logging library, and there is quite a bit of work to implement this with the pointer to byte array and the sizeof, but this to my knowledge the best way to make it flexible enough to became a library as such. As you mentioned, even if you can make the library to resolve, using two different definitions for the same DTU, the library won`t be able to use the same type used in the current project. – homer69 Feb 22 '22 at 10:20
  • still thinking about this and having a reference for a pointer with the size defined instead of a static DTU is definitely the most elegant way of doing it, but it will require a fair bit of coding as there are other services in the codesys application which are using the same structure. – homer69 Mar 25 '22 at 01:15
  • Fred trying to follow your advise, so I have a main library with namespace "LOGS", inside this library I include a library namespace "SAMPLE_STRUCTURE" which is just defining the structure of the sample, which I then use in the main "LOGS" library. The "SAMPLE_STRUCTURE" namespace will have placeholder SAMPLE_STRUCTURE_PROJECT01 (as I want to be able to define different structures for different projects. Now I am in the application software for PROJECT02, I have included the LOGS library but I want to change the structure of SAMPLE_STRUCTURE to use SAMPLE_STRUCTURE_PROJECT02, how to? – homer69 Mar 25 '22 at 02:05
  • in C I would define an opaque structure but I am unsure how to do this in Codesys, I basically want to be able to change the SAMPLE_STRUCTURE used in the LOGS library on the application, so I can keep the common code the same on all the projects with just a different structure type. Thank you for your help – homer69 Mar 25 '22 at 02:22
  • I did figure it out, thank you for the hint. – homer69 Mar 27 '22 at 23:51