comparison PyPlugScanner.cpp @ 24:7d28bed0864e

* Rearrange Python plugin construction. Formerly, the PyPluginAdapter has retained a single plugin instance pointer for each plugin found, and its createPlugin method has simply returned a new PyPlugin object wrapping the same instance pointer. This has a couple of negative consequences: - Because construction of the actual Python instance occurred before the wrapper was constructed, it was not possible to pass arguments (i.e. the sample rate) from the wrapper constructor to the Python plugin instance constructor -- they had to be passed later, to initialise, disadvantaging those plugins that would like to use the sample rate for parameter & step/block size calculations etc - Because there was only a single Python plugin instance, it was not possible to run more than one instance at once with any isolation This rework instead stores the Python class pointer (rather than instance pointer) in the PyPluginAdapter, and each PyPlugin wrapper instance creates its own Python plugin instance. What could possibly go wrong?
author cannam
date Mon, 17 Aug 2009 15:22:06 +0000
parents 3af6b5990ad8
children 7648f3f2fa14
comparison
equal deleted inserted replaced
23:535d559300dc 24:7d28bed0864e
60 //foreach m_path listFiles then return vector<pyPlugs> 60 //foreach m_path listFiles then return vector<pyPlugs>
61 //format: FullPathString/FileName.py:ClassName 61 //format: FullPathString/FileName.py:ClassName
62 62
63 vector<string> pyPlugs; 63 vector<string> pyPlugs;
64 string pluginKey; 64 string pluginKey;
65 PyObject *pyClassInstance; 65 PyObject *pyClass;
66 66
67 for (size_t i = 0; i < m_path.size(); ++i) { 67 for (size_t i = 0; i < m_path.size(); ++i) {
68 68
69 vector<string> files = listFiles(m_path[i],"py"); 69 vector<string> files = listFiles(m_path[i],"py");
70 70
72 fi != files.end(); ++fi) { 72 fi != files.end(); ++fi) {
73 string script = *fi; 73 string script = *fi;
74 if (!script.empty()) { 74 if (!script.empty()) {
75 string classname=script.substr(0,script.rfind('.')); 75 string classname=script.substr(0,script.rfind('.'));
76 pluginKey=joinPath(m_path[i],script)+":"+classname; 76 pluginKey=joinPath(m_path[i],script)+":"+classname;
77 pyClassInstance = getScriptInstance(m_path[i],classname); 77 pyClass = getScriptClass(m_path[i],classname);
78 if (pyClassInstance == NULL) 78 if (pyClass == NULL)
79 cerr << "Warning: Syntax error in VamPy plugin: " 79 cerr << "Warning: Syntax error in VamPy plugin: "
80 << classname << ". Avoiding plugin." << endl; 80 << classname << ". Avoiding plugin." << endl;
81 else { 81 else {
82 pyPlugs.push_back(pluginKey); 82 pyPlugs.push_back(pluginKey);
83 m_pyInstances.push_back(pyClassInstance); 83 m_pyClasses.push_back(pyClass);
84 } 84 }
85 //pyPlugs.push_back(pluginKey); 85 //pyPlugs.push_back(pluginKey);
86 } 86 }
87 } 87 }
88 } 88 }
90 return pyPlugs; 90 return pyPlugs;
91 91
92 } 92 }
93 93
94 94
95 //For now return one class instance found in each script 95 //For now return one class object found in each script
96 vector<PyObject*> 96 vector<PyObject*>
97 PyPlugScanner::getPyInstances() 97 PyPlugScanner::getPyClasses()
98 { 98 {
99 return m_pyInstances; 99 return m_pyClasses;
100 100
101 } 101 }
102 102
103 103
104 //Validate 104 //Validate
105 //This should not be called more than once! 105 //This should not be called more than once!
106 PyObject* 106 PyObject*
107 PyPlugScanner::getScriptInstance(string path, string classname) 107 PyPlugScanner::getScriptClass(string path, string classname)
108 { 108 {
109 109
110 //Add plugin path to active Python Path 110 //Add plugin path to active Python Path
111 string pyCmd = "import sys\nsys.path.append('" + path + "')\n"; 111 string pyCmd = "import sys\nsys.path.append('" + path + "')\n";
112 PyRun_SimpleString(pyCmd.c_str()); 112 PyRun_SimpleString(pyCmd.c_str());
134 PyObject *pyClass = PyDict_GetItemString(pyDict, classname.c_str()); 134 PyObject *pyClass = PyDict_GetItemString(pyDict, classname.c_str());
135 135
136 //Check if class is present and a callable method is implemented 136 //Check if class is present and a callable method is implemented
137 if (pyClass && PyCallable_Check(pyClass)) { 137 if (pyClass && PyCallable_Check(pyClass)) {
138 138
139 //Create an instance 139 return pyClass;
140 PyObject *pyInstance = PyObject_CallObject(pyClass, NULL);
141 //cerr << "__(getInstance) PyPlugin Class: " << m_class << " successfully created.__" << endl;
142 return pyInstance;
143 } 140 }
144 else { 141 else {
145 cerr << "ERROR: callable plugin class could not be found in source: " << classname << endl 142 cerr << "ERROR: callable plugin class could not be found in source: " << classname << endl
146 << "Hint: plugin source filename and plugin class name must be the same." << endl; 143 << "Hint: plugin source filename and plugin class name must be the same." << endl;
147 PyErr_Print(); 144 PyErr_Print();