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