Переглянути джерело

Add multi-dimensional array support for VariableNode code generation

This patch enables the nodeset compiler to create c code for VariableNode
instances with arrayDimensions.
Jannis Voelker 6 роки тому
батько
коміт
4849d4b30a

+ 9 - 2
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -90,8 +90,12 @@ def generateVariableNodeCode(node, nodeset, max_string_length):
         code.append("attr.arrayDimensionsSize = %d;" % node.valueRank)
         code.append("attr.arrayDimensions = (UA_UInt32 *)UA_Array_new({}, &UA_TYPES[UA_TYPES_UINT32]);".format(node.valueRank))
         codeCleanup.append("UA_Array_delete(attr.arrayDimensions, {}, &UA_TYPES[UA_TYPES_UINT32]);".format(node.valueRank))
-        for dim in range(0, node.valueRank):
-            code.append("attr.arrayDimensions[{}] = 0;".format(dim))
+        if len(node.arrayDimensions) == node.valueRank:
+            for idx, v in enumerate(node.arrayDimensions):
+                code.append("attr.arrayDimensions[{}] = {};".format(idx, int(unicode(v))))
+        else:
+            for dim in range(0, node.valueRank):
+                code.append("attr.arrayDimensions[{}] = 0;".format(dim))
 
     if node.dataType is not None:
         if isinstance(node.dataType, NodeId) and node.dataType.ns == 0 and node.dataType.i == 0:
@@ -110,6 +114,9 @@ def generateVariableNodeCode(node, nodeset, max_string_length):
                     [code1, codeCleanup1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset, max_string_length=max_string_length)
                     code += code1
                     codeCleanup += codeCleanup1
+                    if node.valueRank > 0 and len(node.arrayDimensions) == node.valueRank:
+                        code.append("attr.value.arrayDimensionsSize = attr.arrayDimensionsSize;")
+                        code.append("attr.value.arrayDimensions = attr.arrayDimensions;")
                 else:
                     code += generateValueCodeDummy(dataTypeNode, nodeset.nodes[node.id], nodeset)
     return [code, codeCleanup]

+ 7 - 5
tools/nodeset_compiler/nodes.py

@@ -254,6 +254,8 @@ class VariableNode(Node):
                 self.minimumSamplingInterval = float(av)
             elif at == "DataType":
                 self.dataType = RefOrAlias(av)
+            elif  at == "ArrayDimensions":
+                self.arrayDimensions = av.split(",")
 
         for x in xmlelement.childNodes:
             if x.nodeType != x.ELEMENT_NODE:
@@ -264,8 +266,11 @@ class VariableNode(Node):
                 self.dataType = RefOrAlias(av)
             elif x.localName == "ValueRank":
                 self.valueRank = int(unicode(x.firstChild.data))
-            elif x.localName == "ArrayDimensions":
-                self.arrayDimensions = int(unicode(x.firstChild.data))
+            elif x.localName == "ArrayDimensions" and len(self.arrayDimensions) == 0:
+                elements = x.getElementsByTagName("ListOfUInt32");
+                if len(elements):
+                    for idx, v in enumerate(elements[0].getElementsByTagName("UInt32")):
+                        self.arrayDimensions.append(v.firstChild.data)
             elif x.localName == "AccessLevel":
                 self.accessLevel = int(unicode(x.firstChild.data))
             elif x.localName == "UserAccessLevel":
@@ -292,9 +297,6 @@ class VariableNode(Node):
         # reflect the exaxt dimensions attached binary stream.
         if not isinstance(self.value, Value) or len(self.value.value) == 0:
             self.arrayDimensions = []
-        else:
-            # Parser only permits 1-d arrays, which means we do not have to check further dimensions
-            self.arrayDimensions = [len(self.value.value)]
         return True