More pedagogical tests/python. Should be renamed python_ctypes_and_C_pragmas_in_ST or something
authorEdouard Tisserant
Thu, 18 Oct 2012 20:24:11 +0200
changeset 859 dbf82971f09d
parent 858 daafaa8a28fd
child 860 8a51046010d7
More pedagogical tests/python. Should be renamed python_ctypes_and_C_pragmas_in_ST or something
tests/python/beremiz.xml
tests/python/c_code@c_ext/cfile.xml
tests/python/plc.xml
tests/python/python@py_ext/py_ext.xml
--- a/tests/python/beremiz.xml	Thu Oct 18 17:42:29 2012 +0200
+++ b/tests/python/beremiz.xml	Thu Oct 18 20:24:11 2012 +0200
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<BeremizRoot>
+<BeremizRoot URI_location="LOCAL://">
   <TargetType/>
 </BeremizRoot>
--- a/tests/python/c_code@c_ext/cfile.xml	Thu Oct 18 17:42:29 2012 +0200
+++ b/tests/python/c_code@c_ext/cfile.xml	Thu Oct 18 20:24:11 2012 +0200
@@ -3,14 +3,48 @@
   <includes>
 <![CDATA[]]>
   </includes>
-  <variables/>
+  <variables>
+    <variable name="TestInput" type="SINT" class="input"/>
+    <variable name="TestOutput" type="SINT" class="input"/>
+  </variables>
   <globals>
-<![CDATA[void Python_to_C_Call(int value){
-  /* That code should never touch to 
-     variables modified by PLC thread */
-  printf("C code called by Python: %d\n",value);
+<![CDATA[volatile long Lock=0;
+volatile char PtoC=1,CtoP=2;
+
+int Simple_C_Call(int val){
+  return val+1;
 }
-]]>
+
+int Python_to_C_Call(int toC, int *fromC){
+  /* Code called by python should never touch to 
+     variables modified by PLC thread directly
+
+     AtomicCompareExchange comes from 
+     beremiz' runtime implementation */
+
+  int res = 0;
+  if(!AtomicCompareExchange(&Lock, 0, 1)){
+    PtoC=toC;
+    *fromC=CtoP;
+    AtomicCompareExchange(&Lock, 1, 0);
+    res=1;
+  }
+  printf("C code called by Python: toC %d fromC %d\n",toC,*fromC);
+  return res;
+}
+
+int PLC_C_Call(int fromPLC, int *toPLC){
+  /* PLC also have to be realy carefull not to 
+     conflict with asynchronous python access */
+  int res;
+  if(!AtomicCompareExchange(&Lock, 0, 1)){
+      CtoP = fromPLC;
+      *toPLC = PtoC;
+      AtomicCompareExchange(&Lock, 1, 0);
+      return 1;
+  }
+  return 0;
+}]]>
   </globals>
   <initFunction>
 <![CDATA[]]>
--- a/tests/python/plc.xml	Thu Oct 18 17:42:29 2012 +0200
+++ b/tests/python/plc.xml	Thu Oct 18 20:24:11 2012 +0200
@@ -8,7 +8,7 @@
               productVersion="0.0"
               creationDateTime="2008-12-14T16:21:19"/>
   <contentHeader name="Beremiz Python Support Tests"
-                 modificationDateTime="2012-06-08T23:11:45">
+                 modificationDateTime="2012-10-18T20:21:28">
     <coordinateInfo>
       <pageSize x="1024" y="1024"/>
       <fbd>
@@ -63,6 +63,16 @@
                 <BOOL/>
               </type>
             </variable>
+            <variable name="FromC">
+              <type>
+                <SINT/>
+              </type>
+            </variable>
+            <variable name="C_Pragma0">
+              <type>
+                <derived name="C_Pragma"/>
+              </type>
+            </variable>
           </localVars>
         </interface>
         <body>
@@ -202,7 +212,7 @@
               <connectionPointOut>
                 <relPosition x="290" y="15"/>
               </connectionPointOut>
-              <expression>'PLCBinary.Python_to_C_Call(5678)'</expression>
+              <expression>'PLCBinary.Simple_C_Call(5678)'</expression>
             </inVariable>
             <block localId="12" width="125" height="80" typeName="python_eval" instanceName="Block2">
               <position x="650" y="417"/>
@@ -457,9 +467,79 @@
               </connectionPointIn>
               <expression>pytest_var3</expression>
             </outVariable>
+            <outVariable localId="25" height="30" width="60">
+              <position x="820" y="750"/>
+              <connectionPointIn>
+                <relPosition x="0" y="15"/>
+                <connection refLocalId="26" formalParameter="OUT">
+                  <position x="820" y="765"/>
+                  <position x="765" y="765"/>
+                </connection>
+              </connectionPointIn>
+              <expression>FromC</expression>
+            </outVariable>
+            <inVariable localId="1" height="30" width="30">
+              <position x="605" y="750"/>
+              <connectionPointOut>
+                <relPosition x="30" y="15"/>
+              </connectionPointOut>
+              <expression>23</expression>
+            </inVariable>
+            <block localId="26" width="80" height="45" typeName="C_Pragma" instanceName="C_Pragma0">
+              <position x="685" y="735"/>
+              <inputVariables>
+                <variable formalParameter="IN">
+                  <connectionPointIn>
+                    <relPosition x="0" y="30"/>
+                    <connection refLocalId="1">
+                      <position x="685" y="765"/>
+                      <position x="635" y="765"/>
+                    </connection>
+                  </connectionPointIn>
+                </variable>
+              </inputVariables>
+              <inOutVariables/>
+              <outputVariables>
+                <variable formalParameter="OUT">
+                  <connectionPointOut>
+                    <relPosition x="80" y="30"/>
+                  </connectionPointOut>
+                </variable>
+              </outputVariables>
+            </block>
           </FBD>
         </body>
       </pou>
+      <pou name="C_Pragma" pouType="functionBlock">
+        <interface>
+          <outputVars>
+            <variable name="OUT">
+              <type>
+                <SINT/>
+              </type>
+            </variable>
+          </outputVars>
+          <inputVars>
+            <variable name="IN">
+              <type>
+                <SINT/>
+              </type>
+            </variable>
+          </inputVars>
+        </interface>
+        <body>
+          <ST>
+<![CDATA[(* hereafter is a C pragma accessing FB interface in a clean way *)
+{
+  int toPLC;
+  int fromPLC = __GET_VAR(data__->IN);
+  if(PLC_C_Call(fromPLC, &toPLC))__SET_VAR(data__->,OUT,toPLC);
+}
+(* If you do not use __GET_VAR and _SET_VAR macro, expect unexpected *)
+]]>
+          </ST>
+        </body>
+      </pou>
     </pous>
   </types>
   <instances>
--- a/tests/python/python@py_ext/py_ext.xml	Thu Oct 18 17:42:29 2012 +0200
+++ b/tests/python/python@py_ext/py_ext.xml	Thu Oct 18 20:24:11 2012 +0200
@@ -1,11 +1,19 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <Python xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="py_ext_xsd.xsd">
-<![CDATA[import time,sys
+<![CDATA[import time,sys,ctypes
+Python_to_C_Call = PLCBinary.Python_to_C_Call
+Python_to_C_Call.restype = ctypes.c_int
+Python_to_C_Call.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
 
 def MyPythonFunc(arg):
-    print arg
-    PLCBinary.Python_to_C_Call(arg)
+    i = ctypes.c_int()
+    if(Python_to_C_Call(arg, i)):
+        res = i.value
+        print "toC:", arg, "from C:", res
+    else:
+        print "Failed Python_to_C_Call failed"
+        res = None
     sys.stdout.flush()
-    return arg
+    return res
 ]]>
 </Python>