How should I translate char dbcc_name[1] to Delphi? - delphi-xe7

I have a problem to translate the following C++ code to Delphi.
This is the code:
char dbcc_name[1]
And this is what I think what it should be:
dbcc_name : array [0..0] of Char;
However, I know this field should return a name, and not just one character.
So, it maybe something like this:
dbcc_name: array of Char;
Now, this looks nice, but there's no way of predicting how long the name will be, and it will probably return something with a load of rubish and somewhere a #0 terminator in it, but that is -I think- not the proper way.
Would it not be wise to use a pointer to this array?
Like:
dbcc_name: PChar;
Thank you in advance.

You were right the first time, only with the wrong data type. Use AnsiChar instead, which is char in C/C++:
dbcc_name: array[0..0] of AnsiChar;
In Delphi 2009+, Char is an alias for WideChar, which in C/C++ is wchar_t on Windows and char16_t on other platforms.
That being said, in C/C++, it makes sense for a 1-element array to exist in a struct when it represents variable-length data, and is the last field in the struct. In this case, the struct usually exists inside of a larger block of allocated memory. There is no array bounds checking in C/C++, the contents of an array can exceed the bounds of the array as long as it doesn't exceed the bounds of the memory that the array is allocated in. Referring to an array by name decays into a pointer to the first element. It is very common in C to exploit this to define a struct that has variable-length data embedded directly inside of it, that can be referred to by name, without having to allocate the data elsewhere in memory. This is especially useful in embedded systems with limited memory.
There are several structs in the Win32 API that use this approach for variable-length data. Raymond Chen discusses this in more detail on his blog:
Why do some structures end with an array of size 1?

You will most likely use either array[0..0] of char or just char, with some caveats. The code below assumes you are using a Windows API and I make assumptions based on one specific Windows Message record that matches your description.
If you are using char dbcc_name[1] as defined in DEV_BROADCAST_DEVICEINTERFACE in C its a char in the DEV_BROADCAST_DEVICEINTERFACE_A structure, but a wchar_t in the DEV_BROADCAST_DEVICEINTERFACE_W structure. NOTE: char in C maps to AnsiChar in Delphi and wchar_t maps to char in Delphi.
With the W strucutre I declare this in Delphi as dbcc_name: char; to read, I simply use PChar(#ARecordPtr^.dbcc_name). Your C++ sample seemingly uses the A struct, a straight translation to Delphi would mean a using the A structure with AnsiChar and using PAnsiChar to read, just replace in the code above.
However, a new Delphi project will by default use the Unicode version (or W imports) of a Windows API so that is why my sample below is written for Unicode.
In my implementation I simply have it defined as char. Some developers like the array[0..0] of char syntax because it leaves a clue of variable length array at that position. It is a more accurate translation, but I find it adds little value.
Example:
PDEV_BROADCAST_DEVICEINTERFACE = ^DEV_BROADCAST_DEVICEINTERFACE;
DEV_BROADCAST_DEVICEINTERFACE = record
dbcc_size: DWORD;
dbcc_devicetype: DWORD; // = DBT_DEVTYP_DEVICEINTERFACE
dbcc_reserved: DWORD;
dbcc_classguid: TGUID;
dbcc_name: Char; // <--- [HERE IT IS]. Use AnsiChar is using the A record instead of the W Record
end;
and to use it
procedure TFoo.WMDeviceChange(var AMessage: TMessage);
var
LUsbDeviceName: string;
LPDeviceBroadcastHeader: PDEV_BROADCAST_HDR;
LPBroadcastDeviceIntf: PDEV_BROADCAST_DEVICEINTERFACE;
begin
if (AMessage.wParam = DBT_DEVICEARRIVAL) then
begin
LPDeviceBroadcastHeader := PDEV_BROADCAST_HDR(AMessage.LParam);
if LPDeviceBroadcastHeader^.dbch_devicetype = DBT_DEVTYP_DEVICEINTERFACE then
begin
LPBroadcastDeviceIntf := PDEV_BROADCAST_DEVICEINTERFACE(LPDeviceBroadcastHeader);
LUsbDeviceName := PChar(#LPBroadcastDeviceIntf^.dbcc_name); // <--- [HERE IT IS USED] Use PAnsiChar if using the A Record instead of the W Record
...
end;
end;
end;
See more in my post on pointers and structures and for more explanation on the odd use of a single character array see the the "Records with Variable Length Arrays" section in my post on arrays and pointer math.

Related

Why use pointers and reference in codesys V3?

My question is: what are the benefits of using pointers and reference to?
I am new to codesys and in my previous job, I programmed in TIA portal (Siemens) and Sysmac Studio (Omron) and never came across pointers or something similar. I think I understand how they work but not sure when I should be using them myself.
For example, I just received a function block from a supplier:
Why don't they just have an array for input and output?
First of all, if you have ever used the VAR_IN_OUT declaration, then you have already used references, since that is equivalent to a VAR with REFERENCE TO.
As for the uses, there are mainly 4 that I can think of right now:
Type Punning, which you can also achieve using a UNION, but you may not want to have to create a union for every single reinterpretation cast in your code.
TL; DR: To save memory and copy execution time. Whenever you pass some data to a function/function block, it gets copied. This is not a big problem if your PLC has enough CPU power and memory, however if you are dealing with especially huge data on a low end PLC, then you may either exceed real time execution constraints, or run out of memory. When you pass a pointer/reference however, no matter how big the data is only the pointer/reference gets copied and passed, which is 4 bytes in 32 bit system, and 8 bytes in a 64 bit one.
In C style languages you'd use pointers/references when you want a function to return multiple values without the hassle of creating a custom structure every time. You can do the same here to, however in CODESYS function can have multiple outputs, for example:
VAR_OUPUT
out1 : INT; (*1st output variable *)
out2 : INT; (*2nd output variable *)
//...
END_VAR
And finally, as I mentioned at the very beginning, when you want to pass some data that needs to be modified in the function itself, in other words, where you can use VAR_IN_OUT you can also use pointers/references. One Special case where you will have to use a pointer is if you have a Function Block that receives some data in the FB_Init (initialization/construction) function and stores it locally. In such case you would have a pointer as a local variable in the function block, and take the address of the variable in the FB_Init function. Same applies if you have a structure that needs to reference another structure or some data.
PS. There are probably some other uses I missed. One of the main uses in other languages is for dynamic memory allocations, but in CODESYS this is disabled by default and not all PLCs support it, and hardly anyone (that I know) uses it.
EDIT: Though this has been accepted, I want to bring a real life example of us using pointers:
Suppose we want to have a Function Block that calculates the moving average on a given number series. A simple approach would be something like this:
FUNCTION_BLOCK MyMovingAvg
VAR_INPUT
nextNum: INT;
END_VAR
VAR_OUTPUT
avg: REAL;
END_VAR
VAR
window: ARRAY [0..50] OF INT;
currentIndex: UINT;
END_VAR
However, this has the problem that the moving window size is static and predefined. If we wanted to have averages for different window sizes we would either have to create several function blocks for different window sizes, or do something like this:
FUNCTION_BLOCK MyMovingAvg
VAR CONSTANT
maxWindowSize: UINT := 100;
END_VAR
VAR_INPUT
nextNum: INT;
windowSize: UINT (0..maxWindowSize);
END_VAR
VAR_OUTPUT
avg: REAL;
END_VAR
VAR
window: ARRAY [0..maxWindowSize] OF INT;
currentIndex: UINT;
END_VAR
where we would only use the elements of the array from 0 to windowSize and the rest would be ignored. This however also has the problems that we can't use window sizes more than maxWindowSize and there's potentially a lot of wasted memory if maxWindowSize is set high.
There are 2 ways to get a truly general solution:
Use dynamic allocations. However, as I mentioned previously, this isn't supported by all PLCs, is disabled by default, has drawbacks (you'll have to split you memory into two chunks), is hardly used and is not very CODESYS-like.
Let the user define the array of whatever size they want and pass the array to our function block:
FUNCTION_BLOCK MyMovingAvg
VAR_INPUT
nextNum: INT;
END_VAR
VAR_OUTPUT
avg: REAL;
END_VAR
VAR
windowPtr: POINTER TO INT;
windowSize: DINT;
currentIndex: UINT;
END_VAR
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL;
bInCopyCode: BOOL;
END_VAR
VAR_IN_OUT // basically REFERENCE TO
window_buffer: ARRAY [*] OF INT; // array of any size
END_VAR
THIS^.windowPtr := ADR(window_buffer);
THIS^.windowSize := UPPER_BOUND(window_buffer, 1) - LOWER_BOUND(window_buffer, 1) + 1;
// usage:
PROGRAM Main
VAR
avgWindow: ARRAY [0..123] OF INT; // whatever size you want!
movAvg: MyMovingAvg(window_buffer := avgWindow);
END_VAR
movAvg(nextNum := 5);
movAvg.avg;
The same principle can be applied to any function block that operates on arrays (for example, we also use it for sorting). Moreover, similarly you may want to have a function that works on any integer/floating number. For that you may use one of the ANY types which is basically a structure that holds a pointer to the first byte of the data, the size of the data (in bytes) and a type enum.

STM32F4 UART half word addressing

Trying to roll my own code for STM32F4 UART.
A peculiarity of this chip is that if you use byte addressing as the GNAT compiler does when setting a single bit, the corresponding bit in the other byte of the half word is set. The data sheet says use half word addressing. Is there a way to tell the compiler to do this? I tried
for CR1_register'Size use 16;
but this had no effect. Writing the whole 16 bit word works, but you lose the ability to set named bits.
The GNAT way to do this, as used in the AdaCore Ada Drivers Library, is to use the GNAT-only aspect Volatile_Full_Access, about which the GNAT Reference Manual says
This is similar in effect to pragma Volatile, except that any reference to the object is guaranteed to be done only with instructions that read or write all the bits of the object. Furthermore, if the object is of a composite type, then any reference to a subcomponent of the object is guaranteed to read and/or write all the bits of the object.
The intention is that this be suitable for use with memory-mapped I/O devices on some machines. Note that there are two important respects in which this is different from pragma Atomic. First a reference to a Volatile_Full_Access object is not a sequential action in the RM 9.10 sense and, therefore, does not create a synchronization point. Second, in the case of pragma Atomic, there is no guarantee that all the bits will be accessed if the reference is not to the whole object; the compiler is allowed (and generally will) access only part of the object in this case.
Their code is
-- Control register 1
type CR1_Register is record
-- Send break
SBK : Boolean := False;
...
end record
with Volatile_Full_Access, Size => 32,
Bit_Order => System.Low_Order_First;
for CR1_Register use record
SBK at 0 range 0 .. 0;
...
end record;
Portable way is to do this explicitly: read whole record, modify, then write it back. As long as it is declared Volatile a compiler will not optimize reads and writes out.
-- excerpt from my working code --
declare
R : Control_Register_1 := Module.CR1;
begin
R.UE := True;
Module.CR1 := R;
end;
This is very verbose, but it does its work.

Why is fmt.Println not consistent when printing pointers?

I'm an experienced programmer but have never before touched Go in my life.
I just started playing around with it and I found that fmt.Println() will actually print the values of pointers prefixed by &, which is neat.
However, it doesn't do this with all types. I'm pretty sure it is because the types it does not work with are primitives (or at least, Java would call them that, does Go?).
Does anyone know why this inconsistent behaviour exists in the Go fmt library? I can easily retrieve the value by using *p, but for some reason Println doesn't do this.
Example:
package main
import "fmt"
type X struct {
S string
}
func main() {
x := X{"Hello World"}
fmt.Println(&x) // &{Hello World} <-- displays the pointed-to value prefixed with &
fmt.Println(*(&x)) // {Hello World}
i := int(1)
fmt.Println(&i) // 0x10410028 <-- instead of &1 ?
fmt.Println(*(&i)) // 1
}
The "technical" answer to your question can be found here:
https://golang.org/src/fmt/print.go?#L839
As you can see, when printing pointers to Array, Slice, Struct or Map types, the special rule of printing "&" + value applies, but in all other cases the address is printed.
As for why they decided to only apply the rule for those, it seems the authors considered that for "compound" objects you'd be interested in always seeing the values (even when using a pointer), but for other simple values this was not the case.
You can see that reasoning here, where they added the rule for the Map type which was not there before:
https://github.com/golang/go/commit/a0c5adc35cbfe071786b6115d63abc7ad90578a9#diff-ebda2980233a5fb8194307ce437dd60a
I would guess this had to do with the fact that it is very common to use for example pointers to Struct to pass them around (so many times you'd just forget to de-reference the pointer when wanting to print the value), but no so common to use pointers to int or string to pass those around (so if you were printing the pointer you were probably interested in seeing the actual address).

What is the model of value vs. reference in Nim?

NOTE: I am not asking about difference between pointer and reference, and for this question it is completely irrelevant.
One thing I couldn't find explicitly stated -- what model does Nim use?
Like C++ -- where you have values and with new you create pointers to data (in such case the variable could hold pointer to a pointer to a pointer to... to data)?
Or like C# -- where you have POD types as values, but user defined objects with referenced (implicitly)?
I spotted only dereferencing is automatic, like in Go.
Rephrase. You define your new type, let's say Student (with name, university, address). You write:
var student ...?
to make student hold actual data (of Student type/class)
to make student hold a pointer to the data
to make student hold a pointer to a pointer to the data
Or some from those points are impossible?
By default the model is of passing data by value. When you create a var of a specific type, the compiler will allocate on the stack the required space for the variable. Which is expected, as Nim compiles to C, and complex types are just structures. But like in C or C++, you can have pointers too. There is the ptr keyword to get an unsafe pointer, mostly for interfacing to C code, and there is a ref to get a garbage collected safe reference (both documented in the References and pointer types section of the Nim manual).
However, note that even when you specify a proc to pass a variable by value, the compiler is free to decide to pass it internally by reference if it considers it can speed execution and is safe at the same time. In practice the only time I've used references is when I was exporting Nim types to C and had to make sure both C and Nim pointed to the same memory. Remember that you can always check the generated C code in the nimcache directory. You will see then that a var parameter in a proc is just a pointer to its C structure.
Here is an example of a type with constructors to be created on the stack and passed in by value, and the corresponding pointer like version:
type
Person = object
age: int
name: string
proc initPerson(age: int, name: string): Person =
result.age = age
result.name = name
proc newPerson(age: int, name: string): ref Person =
new(result)
result.age = age
result.name = name
when isMainModule:
var
a = initPerson(3, "foo")
b = newPerson(4, "bar")
echo a.name & " " & $a.age
echo b.name & " " & $b.age
As you can see the code is essentially the same, but there are some differences:
The typical way to differentiate initialisation is to use init for value types, and new for reference types. Also, note that Nim's own standard library mistakes this convention, since some of the code predates it (eg. newStringOfCap does not return a reference to a string type).
Depending on what your constructors actually do, the ref version allows you to return a nil value, which you can treat as an error, while the value constructor forces you to raise an exception or change the constructor to use the var form mentioned below so you can return a bool indicating success. Failure tends to be treated in different ways.
In C-like languages theres is an explicit syntax to access either the memory value of a pointer or the memory value pointed by it (dereferencing). In Nim there is as well, and it is the empty subscript notation ([]). However, the compiler will attempt to automatically put those to avoid cluttering the code. Hence, the example doesn't use them. To prove this you can change the code to read:
echo b[].name & " " & $b[].age
Which will work and compile as expected. But the following change will yield a compiler error because you can't dereference a non reference type:
echo a[].name & " " & $a[].age
The current trend in the Nim community is to get rid of single letter prefixes to differentiate value vs reference types. In the old convention you would have a TPerson and an alias for the reference value as PPerson = ref TPerson. You can find a lot of code still using this convention.
Depending on what exactly your object and constructor need to do, instead of having a initPerson returning the value you could also have a init(x: var Person, ...). But the use of the implicit result variable allows the compiler to optimise this, so it is much more a taste preference or requirements of passing a bool to the caller.
It can be either.
type Student = object ...
is roughly equivalent to
typedef struct { ... } Student;
in C, while
type Student = ref object ...
or
type Student = ptr object ...
is roughly equivalent to
typedef struct { ... } *Student;
in C (with ref denoting a reference that is traced by the garbage collector, while ptr is not traced).

How to make a generic struct to contain any CSS properties' values

I want to write my own simplified CSS parser for my own purposes. It have to recognize a few properties (not all of them, of course). So, I projected the architecture, and now want to project the minor details.
Right now I need to create the universal structure which can contain the value of any CSS property. I thought about union with structs for every possibly processing property, but it looks like square wheel for me - there are ~146 different properties (I want to provide support for only about 20-40, but that doesn't matter) - so I will need to create a union with 146 different structures and moreover describe this structures. My project is about 60 KB right now, I don't want to make it grow up to 60 MB yet.
I thought about char value[255], but it makes a limit for every value to be less then 255 (or N) symbols. What can I do to solve this little problem?
One (rather simple) way would be to approach it like so
struct CSS {
char *property;
char *value;
}
Then, while parsing a CSS doc or whatever way you want to fill it, allocate the structure with malloc.
You could on top/aside from that include a linked list, so that when you want to free the allocated memory you simply walk through the list and free all the allocated char* variables. The struct could then look like this:
struct CSS_property {
char *property;
char *value;
struct CSS_property *next;
}
Where next would contain a pointer to the next struct if there is one or NULL if there ain't
Finally, I suppose you'd need a type to hold the matcher. Maybe it could look like this:
struct CSS_matcher {
char *matcher;
struct CSS_property *properties;
struct CSS_matcher *next;
}
The properties pointer would point to the first property of this block, the CSS_matcher could in itself be yet another linked list for all matchers you'd encounter in a CSS file.
I'm not familiar with the right CSS terminology, I'm sure they don't actually call matchers matchers...

Resources