More pedagogical tests/python. Should be renamed python_ctypes_and_C_pragmas_in_ST or something
--- 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>