Array of user-defined string as OUT port in FB with C#
Hello,
I was looking https://github.com/PLCnext/CSharpExamples and several posts here in the Community ([url=https://www.plcnext-community.net/en/discussions-2-offcanvas/arrays-in-c.html]Arrays in C#[/url] or [url=https://www.plcnext-community.net/en/discussions-2-offcanvas/return-array-from-c-fb.html]Return Array From C# FB[/url]) but I don't have quitte clear how to proceed (or even if it's possible) to create an array of user-defined strings in C#.
[list]
[*]To create my own string size it's clear, I have to declare something like:
[/list]
[code type="markup"]
// Define a string data type with a maximum string length of 200 characters
// Size is string length + 4 byte header + 1 byte terminating zero + padding for two byte alignment
// Mark the declaration with a String attribute and define the length
[String(200)]
[StructLayout(LayoutKind.Explicit, Size = 206)]
public struct TString200
{
// Fields
[FieldOffset(0)]
public IecStringEx s;
// Methods
//ctor is needed to set the maximum size and called in the initialization
public void ctor()
{
this.s.maximumLength = 200;
}
public void rctor()
{
this.s.maximumLength = 200;
}
}
[/code]
[list]
[*]To create my own array, it's a bit confusing because create a struct is recommended, but it's also more or less clear. I have to declare something like:
[/list]
[code type="markup"]
// The IecArray must be defined as a struct with a fixed size.
// The array definition MUST have following Attributes:
// 1. Array (Actually only one-dimensional arrays are supported by the PCWorx Engineer)
// 2. ArrayDimension
// 3. DataType to define the data type of the array elements
[Array(1), ArrayDimension(0, ArrayProperties.lowerBound, ArrayProperties.upperBound), DataType("TString200")]
[StructLayout(LayoutKind.Explicit, Size = ArrayProperties.size)]
public struct MyArray
{
// Helper containing constants to have a
// clear and maintainable definition for boundaries and size
struct ArrayProperties
{
public const int lowerBound = 0;
public const int upperBound = 9;
// the size must be changed to the correct size of your elements times the amount of elements
public const int size = (upperBound - lowerBound + 1) * sizeof(int);
}
// Fields
// The field "Anchor" defines the beginning of the array.
[FieldOffset(0)]
// The Anchor's data type is the child data type of the array
public int Anchor;
// The constants LB and UB define the upper and lower bound. Boundaries will be checked by using them.
public const int LB = ArrayProperties.lowerBound;
public const int UB = ArrayProperties.upperBound;
public int this[int index]
{
get
{
if (index >= LB && index <= UB)
{
unsafe
{
fixed (int* pValue = &Anchor)
{
int result = *(pValue + index);
return result;
}
}
}
else
{
throw new IndexOutOfRangeException();
}
}
set
{
if (index >= LB && index <= UB)
{
unsafe
{
fixed (int* pValue = &Anchor)
{
*(pValue + index) = value;
}
}
}
else
{
throw new IndexOutOfRangeException();
}
}
}
}
[/code]
[list]
[*][b]When I have to give the data type to the array, it's supposed that I have to put my-own-string-type in the attribute DataType("TString200" ) ??[/b]
[*][b]When I wnat to use it as a PORT, it's enough with[/b]
[code type="markup"]
[Output]
public MyArray iIN;
[/code]
[b]or it's required like[/b]
[code type="markup"]
[Output, DataType(nameof(MyArray ))]
public MyArray OUT;
[/code]
[b]??[/b]
[/list]
Then, after having this array defined in C# FB, what is needed to define from PnE to link a variable with this paramenter, an array or a struct?
Thanks.
I was looking https://github.com/PLCnext/CSharpExamples and several posts here in the Community ([url=https://www.plcnext-community.net/en/discussions-2-offcanvas/arrays-in-c.html]Arrays in C#[/url] or [url=https://www.plcnext-community.net/en/discussions-2-offcanvas/return-array-from-c-fb.html]Return Array From C# FB[/url]) but I don't have quitte clear how to proceed (or even if it's possible) to create an array of user-defined strings in C#.
[list]
[*]To create my own string size it's clear, I have to declare something like:
[/list]
[code type="markup"]
// Define a string data type with a maximum string length of 200 characters
// Size is string length + 4 byte header + 1 byte terminating zero + padding for two byte alignment
// Mark the declaration with a String attribute and define the length
[String(200)]
[StructLayout(LayoutKind.Explicit, Size = 206)]
public struct TString200
{
// Fields
[FieldOffset(0)]
public IecStringEx s;
// Methods
//ctor is needed to set the maximum size and called in the initialization
public void ctor()
{
this.s.maximumLength = 200;
}
public void rctor()
{
this.s.maximumLength = 200;
}
}
[/code]
[list]
[*]To create my own array, it's a bit confusing because create a struct is recommended, but it's also more or less clear. I have to declare something like:
[/list]
[code type="markup"]
// The IecArray must be defined as a struct with a fixed size.
// The array definition MUST have following Attributes:
// 1. Array (Actually only one-dimensional arrays are supported by the PCWorx Engineer)
// 2. ArrayDimension
// 3. DataType to define the data type of the array elements
[Array(1), ArrayDimension(0, ArrayProperties.lowerBound, ArrayProperties.upperBound), DataType("TString200")]
[StructLayout(LayoutKind.Explicit, Size = ArrayProperties.size)]
public struct MyArray
{
// Helper containing constants to have a
// clear and maintainable definition for boundaries and size
struct ArrayProperties
{
public const int lowerBound = 0;
public const int upperBound = 9;
// the size must be changed to the correct size of your elements times the amount of elements
public const int size = (upperBound - lowerBound + 1) * sizeof(int);
}
// Fields
// The field "Anchor" defines the beginning of the array.
[FieldOffset(0)]
// The Anchor's data type is the child data type of the array
public int Anchor;
// The constants LB and UB define the upper and lower bound. Boundaries will be checked by using them.
public const int LB = ArrayProperties.lowerBound;
public const int UB = ArrayProperties.upperBound;
public int this[int index]
{
get
{
if (index >= LB && index <= UB)
{
unsafe
{
fixed (int* pValue = &Anchor)
{
int result = *(pValue + index);
return result;
}
}
}
else
{
throw new IndexOutOfRangeException();
}
}
set
{
if (index >= LB && index <= UB)
{
unsafe
{
fixed (int* pValue = &Anchor)
{
*(pValue + index) = value;
}
}
}
else
{
throw new IndexOutOfRangeException();
}
}
}
}
[/code]
[list]
[*][b]When I have to give the data type to the array, it's supposed that I have to put my-own-string-type in the attribute DataType("TString200" ) ??[/b]
[*][b]When I wnat to use it as a PORT, it's enough with[/b]
[code type="markup"]
[Output]
public MyArray iIN;
[/code]
[b]or it's required like[/b]
[code type="markup"]
[Output, DataType(nameof(MyArray ))]
public MyArray OUT;
[/code]
[b]??[/b]
[/list]
Then, after having this array defined in C# FB, what is needed to define from PnE to link a variable with this paramenter, an array or a struct?
Thanks.
Comments
well, this is indeed not very intuitive.
I've create a small example which hopefully helps in your implementation.
Type defnition
Usage in a functionblock
I'll tidy this example up and add this in our GitHub example collection.
BR,
Frank