Common Vision Blox 15.0
Loading...
Searching...
No Matches
Python Scripting

Extending Applications

Python scripting enables extending C++ and .Net applications with Python scripts. It allows seamless data exchange between the native SDK and Python: existing SDK objects can be passed into Python for processing, and the resulting objects or values can be returned back to the C++ or .NET environment. This makes it possible to enrich applications with Python’s flexibility and ecosystem while keeping the performance and structure of a core application.

Prerequisites

Unlike many common Python extension mechanisms, we do not rely on an embedded Python runtime shipped with the Common Vision Blox. Instead, it attaches to the Python installation already available on the system. This allows users to work with their preferred Python environment, but requires:

  • Python (64-bit) version 3.8 or higher installed and available on the command line
  • cvb-x.y.z-py3-none-any.whl installed in the user site-packages of the desired Python installation
Note
The cvb Python wheel is located at %CVB%/Lib/Python (Windows) and /opt/cvb/python.

API Usage

You can run Python scripts from you .NET or C++ application. In order to to do that you must create a Python context first. Be aware that this can be done only one in a process. In order to load a Python script from a custom location add the folder to Python's search path. Finally, you can import your script using it as normal Python module. See also ScriptLab to try Python scripting within an application.

Initialization and Import

#include <cvb/py_script/context.hpp>
// append ./MyMyScriptLocation to sys.path
context->AppendToSysPath("MyScriptLocation");
// import MyScriptName
auto module = context->Import("MyScriptName");
static ContextPtr CreateOrGet()

var context = Context.CreateOrGet();
// append ./MyMyScriptLocation to sys.path
context.AppendToSysPath("MyScriptLocation");
// import MyScriptName
var module = context.Import("MyScriptName");
PythonObject Import(string moduleName)

Once everything is setup you can continue calling into the script. On the .Net/C++ side you will only interact with generic Python objects. Even your module itself is a generic Python object. In order to call into an object's method you must first get the type object from the module. Then create an instance of this type. After that you can access the method by name. The method is also just another generic Python object.

In order to call the method with arguments you must first pack all arguments into a tuple. The factory method supports all basic data types including many more complex CVB types. After running the method, you can convert the result into the expected type.

Interacting with Python

#include <cvb/py_script/object.hpp>
// setup
auto myClassType = module->Attribute("MyClass");
auto myClassInstance = myClassType->Run();
auto myMethod = myClassInstance->Attribute("my_method");
// call
auto myMethodArgs = Cvb::PyScript::Object::MakeTuple(imageIn, ...);
auto result = myMethod->Run(*myMethodArgs);
auto imageOut = result->As<Cvb::ImagePtr>();
static ObjectPtr MakeTuple(T &&...args)
std::shared_ptr< Image > ImagePtr

// setup
var myClassType = module.Attribute("MyClass");
var myClassInstance = myClassType.Run();
var myMethod = myClassInstance.Attribute("my_method");
// call
var myMethodArgs = PythonObject.MakeTuple(imageIn, ...);
var result = myMethod.Run(myMethodArgs);
var imageOut = result.As<Image>();
static PythonObject MakeTuple(params object[] args)

Debugging

It is possible to break into your python code. This can be done by attaching debugpy to your process. For convenience this can be done during context creation. You can activate and configure how the context waits for a debugger in %CVBDATA%/config//CVPyScriptConf.json.

{
"active": false,
"address": "localhost",
"port": 5678,
"timeout": 10
}

Once the context is in the waiting state, you can attach to your process from VS Code using the following launch.json. Note that debugpy only attaches to the thread the context was created in. To debug other threads you must attach debugpy manually.

{
"version": "1.0.0",
"configurations": [
{
"name": "Attach to Python",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"justMyCode": false
}
]
}