Initialize and deinitialize API
This section provides an overview of how to get started with Simplygon APIs.
C++ API
The Simplygon API loader provides an initialization function that must be run before any class in the API can be used. The initialization function creates a variable with the ISimplygon interface, which is used to create other API objects. All the return values of the initialization function are listed in the API reference for the function.
The deinitialization function must be called after all the Simplygon objects have been deallocated, i.e all smart pointers must have gone out of scope, including global pointers.
Simplygon::ISimplygon * sg = nullptr;
// Initialize the SDK
Simplygon::EErrorCodes initVal = Simplygon::Initialize( &sg );
// Make sure the SDK initialized correctly
if( initVal != Simplygon::EErrorCodes::NoError )
{
// Failed to initialize, check the error message
}
// Do some processing using the SDK. Do not put smart pointers in the same scope as
// the Deinitialize call, or you must explicitly set them to null before Deinitialize
// is called. The easiest way to ensure this is to put the processing in a separate function
// Deinitialize the SDK
Simplygon::Deinitialize( sg );
The loader will by default look for the Simplygon DLL in the following directories, in order:
- Custom paths set with
Simplygon::AddSearchPath
function - Current working directory
- Calling process executable directory
- Path given by the
SIMPLYGON_10_PATH
environment variable, which is created by the installer if it does not already exist.
Python API
Simplygon installer installs a helper Simplygon loader Python module called simplygon_loader
to the version specific site-packages
directories in %appdata%\Python
.
This loader module has one method; init_simplygon()
.
init_simplygon()
method takes two optional arguments: simplygon_dll_path
, which allows the user to pass the full path to the Simplygon DLL and license_data
that can be used to pass license file data.
IMPORTANT NOTE
When using the Simplygon Python API, it is important to note that the garbage collector needs to be controlled explicitly to gain full control over Simplygon's deinitialization. Use import gc
and run gc.collect()
explicitly after assigning None
to the sg
variable like in the example below to be 100% sure that Simplygon can be successfully deinitialized.
from simplygon10 import simplygon_loader
from simplygon10 import Simplygon
import gc
def do_something(sg):
# Do some processing using the SDK
pass
# Initialize the SDK
sg = simplygon_loader.init_simplygon()
# Check if we got an error (sg is None) before continuing
if sg is None:
# An error occured
error = Simplygon.GetLastInitializationError()
error_string = Simplygon.GetErrorString(error)
sys.stderr.write('Initialization failed! {} (error {})\n'.format(error_string, error))
# The printout above is also done internally by simplygon_loader
# The code here is just an example on how to get information about the error
# Due to garbage collection in Python it's important that there is no Simplygon
# data that is allocated/deallocated in the same scope as the the deinitialization
# of Simplygon.
do_something(sg)
# To deinitialize Simplygon explicitly, assign None to the sg variable and then call
# Python's gc.collect() method to force a garbage collection pass
sg = None
gc.collect()
C# API
Initialization of C# API is done calling InitSimplygon()
method available in Loader
class in Simplygon
namespace that takes two out parameters that provides error information in case initialization fails and InitSimplygon()
method returns null
. The Simplygon.Loader
class can be found at SIMPLYGON_10_PATH\DotNet
.
Deinitialization is not needed since initialized variable will be garbage collected when it goes out of scope, hence defining scope with using
in the example below.
using (ISimplygon sg = Simplygon.Loader.InitSimplygon(out simplygonErrorCode, out simplygonErrorMessage))
{
if (simplygonErrorCode == Simplygon.EErrorCodes.NoError)
{
// ... do some processing using the simplygon
}
else
{
// ...check error code out parameter simplygonErrorCode and out error message parameter simplygonErrorMessage
}
}
Threading
If you use Simplygon in multiple threads (for example an async call or a worker thread in a thread pool) where the lifetime of the thread is unknown, the thread termination might occur at the same time as the Simplygon DLL is being unloaded. This will cause issues when the cleanup destructors call into the DLL while it is being torn down. To mitigate this you can call the thread deinitialization explicitly when you are done using the Simplygon SDK in your threads or async calls.
void someWorkerFunction()
{
// This code is executing inside a worker thread in a thread pool or an std::async call
// or similar construct where the thread lifetime is not known.
// ... some processing using the Simplygon API here ...
// The worker is now finished and will no longer use the Simplygon API.
// Trigger the thread deinitialization inside the Simplygon DLL to avoid a termination race
Simplygon::DeinitializeThread();
}
void someWorkerFunction()
{
// This code is executing inside a worker thread in a thread pool or an std::async call
// or similar construct where the thread lifetime is not known.
// ... some processing using the Simplygon API here ...
// The worker is now finished and will no longer use the Simplygon API.
// Trigger the thread deinitialization inside the Simplygon DLL to avoid a termination race
Simplygon.DeinitializeSimplygonThread();
}
from simplygon10 import Simplygon
def someWorkerFunction:
# This code is executing inside a worker thread in a thread pool or an std::async call
# or similar construct where the thread lifetime is not known.
# ... some processing using the Simplygon API here ...
# The worker is now finished and will no longer use the Simplygon API.
# Trigger the thread deinitialization inside the Simplygon DLL to avoid a termination race
Simplygon.DeinitializeSimplygonThread()