annotate PyExtensionManager.h @ 106:76badb3a0bb3 vampy-2.1

Add mechanism to build a "standard" Linux .so using Docker
author Chris Cannam
date Tue, 05 Feb 2019 12:48:59 +0000
parents a6718f9fe942
children
rev   line source
Chris@92 1 /* -*- c-basic-offset: 8 indent-tabs-mode: t -*- */
fazekasgy@37 2 /*
fazekasgy@37 3
fazekasgy@37 4 * Vampy : This plugin is a wrapper around the Vamp plugin API.
fazekasgy@37 5 * It allows for writing Vamp plugins in Python.
fazekasgy@37 6
fazekasgy@37 7 * Centre for Digital Music, Queen Mary University of London.
fazekasgy@37 8 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
fazekasgy@37 9 * for licence information.)
fazekasgy@37 10
fazekasgy@37 11 */
fazekasgy@37 12
fazekasgy@37 13 /*
fazekasgy@37 14 PyExtensionManager: This class is responsible for initialisation
fazekasgy@37 15 and cleanup of the extension module, as well as the loaded plugin
fazekasgy@37 16 module namespaces.
fazekasgy@37 17
fazekasgy@37 18 NOTES: Why do we need to clean up the module?
fazekasgy@37 19
fazekasgy@37 20 The module exposed by Vampy to the embedded interpreter contains
fazekasgy@37 21 callback functions. These functions are accessed via function
fazekasgy@37 22 pointers stored in the extension module's namespace dictionary.
fazekasgy@37 23
fazekasgy@37 24 Unfortunately, when the shared library is unloaded and reloaded
fazekasgy@37 25 during a host session, these addresses might change.
fazekasgy@37 26 Therefore, we reinitialise the module dict before each use.
fazekasgy@37 27 However, this will cause garbage collection errors or segmentation
fazekasgy@37 28 faults, when elements of the dict of the previous session are
fazekasgy@37 29 attempted to free. Therefore, we clear the dictinary describing
fazekasgy@37 30 the module namespace and replace all fuction pointers with Py_None
fazekasgy@37 31 objects in individual plugin module namespaces. The reference
fazekasgy@37 32 count on these can be safely decremented next time vampy is loaded
fazekasgy@37 33 and the namespaces are reinitialised.
fazekasgy@37 34
fazekasgy@37 35 Why doesn't the GC clean this up correctly?
fazekasgy@37 36
fazekasgy@37 37 In a normal Python session the GC would deallocate the module
fazekasgy@37 38 dict at the end. In embedded python, although the GC appears
fazekasgy@37 39 to be called when the shared lib is unloaded, the interpreter
fazekasgy@37 40 is reused. Since there is no C/API call to unload modules,
fazekasgy@37 41 and at the time of unloading vampy the wrapped function pointers
fazekasgy@37 42 are still valid, the GC doesn't collect them, nor are they freed
fazekasgy@37 43 by the interpreter. When vampy is reloaded however, the module
fazekasgy@37 44 dict will contain invalid addresses. The above procedure solves
fazekasgy@37 45 this problem.
fazekasgy@37 46
fazekasgy@37 47
fazekasgy@37 48 */
fazekasgy@37 49
fazekasgy@37 50
fazekasgy@37 51 #ifndef _PYEXTENSIONMANAGER_H_
fazekasgy@37 52 #define _PYEXTENSIONMANAGER_H_
fazekasgy@37 53
fazekasgy@37 54 using std::cerr;
fazekasgy@37 55 using std::endl;
fazekasgy@37 56 using std::string;
fazekasgy@37 57 using std::vector;
fazekasgy@37 58
fazekasgy@37 59 class PyExtensionManager
fazekasgy@37 60 {
fazekasgy@37 61 public:
fazekasgy@37 62 PyExtensionManager();
fazekasgy@37 63 ~PyExtensionManager();
fazekasgy@37 64 bool initExtension();
fazekasgy@37 65 void setPlugModuleNames(vector<string> pyPlugs);
fazekasgy@37 66 void deleteModuleName(string plugKey);
fazekasgy@37 67
Chris@92 68 static const char* m_exposedNames[];
Chris@92 69
fazekasgy@37 70 private:
fazekasgy@37 71 vector<string> m_plugModuleNames;
fazekasgy@37 72 PyObject* m_pyGlobalNamespace;
fazekasgy@37 73 PyObject* m_pyVampyNamespace;
fazekasgy@37 74
fazekasgy@37 75 void cleanAllLocals() const;
fazekasgy@37 76 void cleanLocalNamespace(const char* plugModuleName) const;
fazekasgy@37 77 void updateAllLocals() const;
fazekasgy@37 78 void updateLocalNamespace(const char* plugModuleName) const;
fazekasgy@37 79
fazekasgy@37 80 void printDict(PyObject* inDict) const;
fazekasgy@37 81 bool cleanModule() const;
fazekasgy@37 82
fazekasgy@37 83 };
fazekasgy@37 84
fazekasgy@37 85 #endif
fazekasgy@37 86
fazekasgy@37 87