A shared object is a Linux library which contains code and/or data that can be used between multiple processes. They are binary files and similar to Dynamic Link Libraries (DLLs) in Windows. When a Linux program needs a shared object, it loads it into memory and uses its code and/or data. Shared objects are built with compilers like C or C++. This post shows how shared objects can be used in VCF Automation with the Python runtime environment.
Use Shared Object with Python
For my first experiment I am using the
PureBasic programming language, which is available for Linux, Windows and OS X. However, any other programming language can also be used that supports the building of shared objects. The source code is very easy to understand. Three functions are exposed. The first adds two integer numbers, the second subtracts two integer numbers, the third returns a hello world string, but it only works with Windows, and the fourth returns also a hello world string, and that works with Linux and Windows.
ProcedureDLL.i Add(x.i, y.i)
ProcedureReturn x + y
EndProcedure
ProcedureDLL.l Sub(x.l, y.l)
ProcedureReturn x - y
EndProcedure
ProcedureDLL.s HelloWindows(name.s)
If Trim(name) = #Empty$
ProcedureReturn "Hello world from PureBasic"
Else
ProcedureReturn "Hello " + name + " from PureBasic"
EndIf
EndProcedure
ProcedureDLL.i Hello(name.s)
_name.s = PeekS(@name, -1, #PB_UTF8)
retValue.s = #Empty$
If Trim(_name) = #Empty$
retValue = "Hello world from PureBasic"
Else
retValue = "Hello " + _name + " from PureBasic"
EndIf
*retValue = AllocateMemory(Len(retValue) + 1)
PokeS(*retValue, retValue, Len(retValue), #PB_UTF8)
ProcedureReturn *retValue
EndProcedure
|
I assume that the source code was saved with the name
libPython.pb
.
With the command
./pbcompiler libPython.pb -so libPython.so
the source code is compiled into a shared object.
Now let's take a look at the Python source code that loads the library and executes its functions.
This code is also very easy to understand. The library is loaded, then the first function Add is executed with the numbers 10 and 1. Then the second function Sub is executed with the same numbers. The third function is only called if this program is executed in a Windows environment, which is not the case here. A name is passed to the fourth function and it returns a hello world string. The result is returned as a Python dictionary respectively as VCF Automation Properties.
"""
@module de.stschnell
@version 0.1.0
@runtime python:3.10
@memoryLimit 256000000
@timeout 360
@outputType Properties
Checked with Aria Automation 8.12.0 and 8.16.2
"""
import json
import os.path
import platform
from ctypes import*
def handler(context, inputs):
result = {}
try:
dllName = os.path.dirname(os.path.abspath(__file__))
if platform.system() == "Windows":
dllName += "\\libPython.dll"
elif platform.system() == "Linux":
dllName += "/libPython.so"
libPython = cdll.LoadLibrary(dllName)
libPython.Add.argtypes = [ c_int64, c_int64 ]
libPython.Add.restype = c_int64
resultAdd = libPython.Add(10,1)
result["Addition"] = str(resultAdd)
libPython.Sub.argtypes = [ c_long, c_long ]
libPython.Sub.restype = c_long
resultSub = libPython.Sub(10,1)
result["Substraction"] = str(resultSub)
if platform.system() == "Windows":
libPython.HelloWindows.argtypes = [ c_wchar_p ]
libPython.HelloWindows.restype = c_wchar_p
name = c_wchar_p("Stefan")
resultHelloWindows = libPython.HelloWindows(name)
result["HelloWindows"] = resultHelloWindows
libPython.Hello.argtypes = [ c_char_p ]
libPython.Hello.restype = c_char_p
name = "Stefan".encode("utf-8")
resultHello = libPython.Hello(name)
result["Hello"] = str(resultHello, "utf-8")
outputs = {
"status": "done",
"result": result
}
except Exception as err:
outputs = {
"status": "incomplete",
"error": repr(err),
"result": result
}
return outputs
|
The files must now be combined in a zip file.
This zip file can now be imported as an action.
After we have executed the action, we see the correct and expected results. For addition 10 plus 1 equals 11, for subtraction 10 minus 1 equals 9 and the hello world message.
Conclusion
The use of shared libraries or shared objects is very easy with the Python runtime environment. On this way it is also possible to use more extensive functionalities and possibilities of other programming languages in the context of VCF Automation. Cross-platform development is also easily possible. In this example the library was built as a Windows Dynamic Link Library (DLL) and as a Photon OS Shared Object (SO). The source code was compiled unchanged and then used with different Python versions on the different operating systems.