Commit a232dceb21a97cc3077f83c58aae0e5274b60969

Authored by Austin Blanton
2 parents effd3d22 afe4dc93

Merge pull request #164 from biometrics/string_management

Updates to the c API to handle returning strings more safely
app/br/br.cpp
@@ -171,7 +171,11 @@ public: @@ -171,7 +171,11 @@ public:
171 // Do nothing because we checked for this flag prior to initialization 171 // Do nothing because we checked for this flag prior to initialization
172 } else if (!strcmp(fun, "objects")) { 172 } else if (!strcmp(fun, "objects")) {
173 check(parc <= 2, "Incorrect parameter count for 'objects'."); 173 check(parc <= 2, "Incorrect parameter count for 'objects'.");
174 - printf("%s\n", br_objects(parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*")); 174 + int size = br_objects(NULL, 0, parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*");
  175 + char * temp = new char[size];
  176 + br_objects(temp, size, parc >= 1 ? parv[0] : ".*", parc >= 2 ? parv[1] : ".*");
  177 + printf("%s\n", temp);
  178 + delete [] temp;
175 } else if (!strcmp(fun, "about")) { 179 } else if (!strcmp(fun, "about")) {
176 check(parc == 0, "No parameters expected for 'about'."); 180 check(parc == 0, "No parameters expected for 'about'.");
177 printf("%s\n", br_about()); 181 printf("%s\n", br_about());
openbr/gui/algorithm.cpp
1 #include <QStringList> 1 #include <QStringList>
2 #include <openbr/openbr.h> 2 #include <openbr/openbr.h>
  3 +#include <openbr/openbr_plugin.h>
3 4
4 #include "algorithm.h" 5 #include "algorithm.h"
5 6
@@ -18,7 +19,7 @@ bool br::Algorithm::addAlgorithm(const QString &amp;algorithm, const QString &amp;displa @@ -18,7 +19,7 @@ bool br::Algorithm::addAlgorithm(const QString &amp;algorithm, const QString &amp;displa
18 { 19 {
19 static QStringList availableAlgorithms; 20 static QStringList availableAlgorithms;
20 if (availableAlgorithms.isEmpty()) 21 if (availableAlgorithms.isEmpty())
21 - availableAlgorithms = QString(br_objects("Abbreviation", ".*", false)).split("\n"); 22 + availableAlgorithms = br::Context::objects("Abbreviation", ".*", false);
22 23
23 if (!availableAlgorithms.contains(algorithm)) 24 if (!availableAlgorithms.contains(algorithm))
24 return false; 25 return false;
openbr/gui/gallerytoolbar.cpp
@@ -84,7 +84,7 @@ void br::GalleryToolBar::_enroll(const br::File &amp;input) @@ -84,7 +84,7 @@ void br::GalleryToolBar::_enroll(const br::File &amp;input)
84 galleryLock.lock(); 84 galleryLock.lock();
85 this->input = input; 85 this->input = input;
86 if (input.suffix() == "gal") gallery = input.name + ".mem"; 86 if (input.suffix() == "gal") gallery = input.name + ".mem";
87 - else gallery = QString("%1/galleries/%2.gal[cache]").arg(br_scratch_path(), qPrintable(input.baseName()+input.hash())); 87 + else gallery = QString("%1/galleries/%2.gal[cache]").arg(br::Globals->scratchPath(), qPrintable(input.baseName()+input.hash()));
88 files = br::Enroll(input.flat(), gallery.flat()); 88 files = br::Enroll(input.flat(), gallery.flat());
89 galleryLock.unlock(); 89 galleryLock.unlock();
90 } 90 }
@@ -148,7 +148,7 @@ void br::GalleryToolBar::home() @@ -148,7 +148,7 @@ void br::GalleryToolBar::home()
148 148
149 void br::GalleryToolBar::mean() 149 void br::GalleryToolBar::mean()
150 { 150 {
151 - const QString file = QString("%1/mean/%2.png").arg(br_scratch_path(), input.baseName()+input.hash()); 151 + const QString file = QString("%1/mean/%2.png").arg(br::Globals->scratchPath(), input.baseName()+input.hash());
152 br_set_property("CENTER_TRAIN_B", qPrintable(file)); 152 br_set_property("CENTER_TRAIN_B", qPrintable(file));
153 br::File trainingFile = input; 153 br::File trainingFile = input;
154 br_train(qPrintable(trainingFile.flat()), "[algorithm=MedianFace]"); 154 br_train(qPrintable(trainingFile.flat()), "[algorithm=MedianFace]");
openbr/gui/progress.cpp
1 #include <openbr/openbr.h> 1 #include <openbr/openbr.h>
  2 +#include <openbr/openbr_plugin.h>
2 3
3 #include "progress.h" 4 #include "progress.h"
4 5
@@ -29,7 +30,7 @@ void br::Progress::checkProgress() @@ -29,7 +30,7 @@ void br::Progress::checkProgress()
29 const bool visible = progress >= 0 && progress < 100; 30 const bool visible = progress >= 0 && progress < 100;
30 31
31 if (visible) { 32 if (visible) {
32 - showMessage(br_most_recent_message()); 33 + showMessage(Globals->mostRecentMessage);
33 pbProgress.setValue(progress); 34 pbProgress.setValue(progress);
34 if (progress > 100) pbProgress.setMaximum(0); 35 if (progress > 100) pbProgress.setMaximum(0);
35 else pbProgress.setMaximum(100); 36 else pbProgress.setMaximum(100);
openbr/gui/templateviewer.cpp
@@ -72,7 +72,7 @@ void TemplateViewer::refreshImage() @@ -72,7 +72,7 @@ void TemplateViewer::refreshImage()
72 if (file.isNull() || (format == "Photo")) { 72 if (file.isNull() || (format == "Photo")) {
73 setImage(file, true); 73 setImage(file, true);
74 } else { 74 } else {
75 - const QString path = QString(br_scratch_path()) + "/thumbnails"; 75 + const QString path = QString(br::Globals->scratchPath()) + "/thumbnails";
76 const QString hash = file.hash()+format; 76 const QString hash = file.hash()+format;
77 const QString processedFile = path+"/"+file.baseName()+hash+".png"; 77 const QString processedFile = path+"/"+file.baseName()+hash+".png";
78 if (!QFileInfo(processedFile).exists()) { 78 if (!QFileInfo(processedFile).exists()) {
openbr/gui/transformeditor.cpp
@@ -24,7 +24,7 @@ using namespace br; @@ -24,7 +24,7 @@ using namespace br;
24 br::TransformEditor::TransformEditor(Transform *transform, QWidget *parent) 24 br::TransformEditor::TransformEditor(Transform *transform, QWidget *parent)
25 : QWidget(parent) 25 : QWidget(parent)
26 { 26 {
27 - name.addItems(QString(br_objects("Transform", ".*", false)).split('\n')); 27 + name.addItems(br::Context::objects("Transform", ".*", false));
28 layout.addWidget(&name); 28 layout.addWidget(&name);
29 setLayout(&layout); 29 setLayout(&layout);
30 30
openbr/openbr.cpp
@@ -28,9 +28,27 @@ @@ -28,9 +28,27 @@
28 28
29 using namespace br; 29 using namespace br;
30 30
  31 +static int partialCopy(const QString & string, char * buffer, int buffer_length)
  32 +{
  33 +
  34 + QByteArray byteArray = string.toLocal8Bit();
  35 +
  36 + int copyLength = std::min(buffer_length-1, byteArray.size());
  37 + if (copyLength < 0)
  38 + return byteArray.size() + 1;
  39 +
  40 + memcpy(buffer, byteArray.data(), copyLength);
  41 + buffer[copyLength] = '\0';
  42 +
  43 + return byteArray.size() + 1;
  44 +}
  45 +
31 const char *br_about() 46 const char *br_about()
32 { 47 {
  48 + static QMutex aboutLock;
  49 + QMutexLocker lock(&aboutLock);
33 static QByteArray about = Context::about().toLocal8Bit(); 50 static QByteArray about = Context::about().toLocal8Bit();
  51 +
34 return about.data(); 52 return about.data();
35 } 53 }
36 54
@@ -150,53 +168,14 @@ void br_make_pairwise_mask(const char *target_input, const char *query_input, co @@ -150,53 +168,14 @@ void br_make_pairwise_mask(const char *target_input, const char *query_input, co
150 BEE::makePairwiseMask(target_input, query_input, mask); 168 BEE::makePairwiseMask(target_input, query_input, mask);
151 } 169 }
152 170
153 -const char *br_most_recent_message() 171 +int br_most_recent_message(char * buffer, int buffer_length)
154 { 172 {
155 - static QByteArray byteArray;  
156 - byteArray = Globals->mostRecentMessage.toLocal8Bit();  
157 - return byteArray.data(); 173 + return partialCopy(Globals->mostRecentMessage, buffer, buffer_length);
158 } 174 }
159 175
160 -const char *br_objects(const char *abstractions, const char *implementations, bool parameters) 176 +int br_objects(char * buffer, int buffer_length, const char *abstractions, const char *implementations, bool parameters)
161 { 177 {
162 - static QByteArray objects;  
163 -  
164 - QStringList objectList;  
165 - QRegExp abstractionsRegExp(abstractions);  
166 - QRegExp implementationsRegExp(implementations);  
167 -  
168 - if (abstractionsRegExp.exactMatch("Abbreviation"))  
169 - foreach (const QString &name, Globals->abbreviations.keys())  
170 - if (implementationsRegExp.exactMatch(name))  
171 - objectList.append(name + (parameters ? "\t" + Globals->abbreviations[name] : ""));  
172 -  
173 - if (abstractionsRegExp.exactMatch("Distance"))  
174 - foreach (const QString &name, Factory<Distance>::names())  
175 - if (implementationsRegExp.exactMatch(name))  
176 - objectList.append(name + (parameters ? "\t" + Factory<Distance>::parameters(name) : ""));  
177 -  
178 - if (abstractionsRegExp.exactMatch("Format"))  
179 - foreach (const QString &name, Factory<Format>::names())  
180 - if (implementationsRegExp.exactMatch(name))  
181 - objectList.append(name + (parameters ? "\t" + Factory<Format>::parameters(name) : ""));  
182 -  
183 - if (abstractionsRegExp.exactMatch("Initializer"))  
184 - foreach (const QString &name, Factory<Initializer>::names())  
185 - if (implementationsRegExp.exactMatch(name))  
186 - objectList.append(name + (parameters ? "\t" + Factory<Initializer>::parameters(name) : ""));  
187 -  
188 - if (abstractionsRegExp.exactMatch("Output"))  
189 - foreach (const QString &name, Factory<Output>::names())  
190 - if (implementationsRegExp.exactMatch(name))  
191 - objectList.append(name + (parameters ? "\t" + Factory<Output>::parameters(name) : ""));  
192 -  
193 - if (abstractionsRegExp.exactMatch("Transform"))  
194 - foreach (const QString &name, Factory<Transform>::names())  
195 - if (implementationsRegExp.exactMatch(name))  
196 - objectList.append(name + (parameters ? "\t" + Factory<Transform>::parameters(name) : ""));  
197 -  
198 - objects = objectList.join("\n").toLocal8Bit();  
199 - return objects.data(); 178 + return partialCopy(br::Context::objects(abstractions, implementations, parameters).join('\n'), buffer, buffer_length);
200 } 179 }
201 180
202 bool br_plot(int num_files, const char *files[], const char *destination, bool show) 181 bool br_plot(int num_files, const char *files[], const char *destination, bool show)
@@ -251,15 +230,15 @@ void br_read_pipe(const char *pipe, int *argc, char ***argv) @@ -251,15 +230,15 @@ void br_read_pipe(const char *pipe, int *argc, char ***argv)
251 *argv = rawCharArrayList.data(); 230 *argv = rawCharArrayList.data();
252 } 231 }
253 232
254 -const char *br_scratch_path() 233 +int br_scratch_path(char * buffer, int buffer_length)
255 { 234 {
256 - static QByteArray byteArray;  
257 - byteArray = Context::scratchPath().toLocal8Bit();  
258 - return byteArray.data(); 235 + return partialCopy(Context::scratchPath(), buffer, buffer_length);
259 } 236 }
260 237
261 const char *br_sdk_path() 238 const char *br_sdk_path()
262 { 239 {
  240 + static QMutex sdkLock;
  241 + QMutexLocker lock(&sdkLock);
263 static QByteArray sdkPath = QDir(Globals->sdkPath).absolutePath().toLocal8Bit(); 242 static QByteArray sdkPath = QDir(Globals->sdkPath).absolutePath().toLocal8Bit();
264 return sdkPath.data(); 243 return sdkPath.data();
265 } 244 }
@@ -303,6 +282,8 @@ void br_train_n(int num_inputs, const char *inputs[], const char *model) @@ -303,6 +282,8 @@ void br_train_n(int num_inputs, const char *inputs[], const char *model)
303 282
304 const char *br_version() 283 const char *br_version()
305 { 284 {
  285 + static QMutex versionLock;
  286 + QMutexLocker lock(&versionLock);
306 static QByteArray version = Context::version().toLocal8Bit(); 287 static QByteArray version = Context::version().toLocal8Bit();
307 return version.data(); 288 return version.data();
308 } 289 }
@@ -380,11 +361,9 @@ bool br_img_is_empty(br_template tmpl) @@ -380,11 +361,9 @@ bool br_img_is_empty(br_template tmpl)
380 return t->m().empty(); 361 return t->m().empty();
381 } 362 }
382 363
383 -const char* br_get_filename(br_template tmpl) 364 +int br_get_filename(char * buffer, int buffer_length, br_template tmpl)
384 { 365 {
385 - static QByteArray buffer;  
386 - buffer = reinterpret_cast<Template*>(tmpl)->file.name.toLocal8Bit();  
387 - return buffer.data(); 366 + return partialCopy(reinterpret_cast<Template*>(tmpl)->file.name, buffer, buffer_length);
388 } 367 }
389 368
390 void br_set_filename(br_template tmpl, const char *filename) 369 void br_set_filename(br_template tmpl, const char *filename)
@@ -393,15 +372,11 @@ void br_set_filename(br_template tmpl, const char *filename) @@ -393,15 +372,11 @@ void br_set_filename(br_template tmpl, const char *filename)
393 t->file.name = filename; 372 t->file.name = filename;
394 } 373 }
395 374
396 -const char* br_get_metadata_string(br_template tmpl, const char *key) 375 +int br_get_metadata_string(char * buffer, int buffer_length, br_template tmpl, const char *key)
397 { 376 {
398 Template *t = reinterpret_cast<Template*>(tmpl); 377 Template *t = reinterpret_cast<Template*>(tmpl);
399 - // need an object outside of this scope  
400 - // so the char pointer is valid  
401 - static QByteArray result;  
402 QVariant qvar = t->file.value(key); 378 QVariant qvar = t->file.value(key);
403 - result = QtUtils::toString(qvar).toUtf8();  
404 - return result.data(); 379 + return partialCopy(QtUtils::toString(qvar), buffer, buffer_length);
405 } 380 }
406 381
407 br_template_list br_enroll_template(br_template tmpl) 382 br_template_list br_enroll_template(br_template tmpl)
openbr/openbr.h
@@ -41,6 +41,10 @@ extern &quot;C&quot; { @@ -41,6 +41,10 @@ extern &quot;C&quot; {
41 * \section managed_return_value Managed Return Value 41 * \section managed_return_value Managed Return Value
42 * Memory for <tt>const char*</tt> return values is managed internally and guaranteed until the next call to the function. 42 * Memory for <tt>const char*</tt> return values is managed internally and guaranteed until the next call to the function.
43 * 43 *
  44 + * \section input_string_buffer Input String Buffer
  45 + * Users should input a char * buffer and the size of that buffer. String data will be copied into the buffer, if the buffer is too
  46 + * small, only part of the string will be copied. Returns the buffer size required to contain the complete string.
  47 + *
44 * \section examples Examples 48 * \section examples Examples
45 * - \ref c_face_recognition_evaluation 49 * - \ref c_face_recognition_evaluation
46 * 50 *
@@ -56,7 +60,6 @@ extern &quot;C&quot; { @@ -56,7 +60,6 @@ extern &quot;C&quot; {
56 60
57 /*! 61 /*!
58 * \brief Wraps br::Context::about() 62 * \brief Wraps br::Context::about()
59 - * \note \ref managed_return_value  
60 * \see br_version 63 * \see br_version
61 */ 64 */
62 BR_EXPORT const char *br_about(); 65 BR_EXPORT const char *br_about();
@@ -256,10 +259,10 @@ BR_EXPORT void br_make_pairwise_mask(const char *target_input, const char *query @@ -256,10 +259,10 @@ BR_EXPORT void br_make_pairwise_mask(const char *target_input, const char *query
256 259
257 /*! 260 /*!
258 * \brief Returns the most recent line sent to stderr. 261 * \brief Returns the most recent line sent to stderr.
259 - * \note \ref managed_return_value 262 + * \note \ref input_string_buffer
260 * \see br_progress br_time_remaining 263 * \see br_progress br_time_remaining
261 */ 264 */
262 -BR_EXPORT const char *br_most_recent_message(); 265 +BR_EXPORT int br_most_recent_message(char * buffer, int buffer_length);
263 266
264 /*! 267 /*!
265 * \brief Returns names and parameters for the requested objects. 268 * \brief Returns names and parameters for the requested objects.
@@ -268,10 +271,10 @@ BR_EXPORT const char *br_most_recent_message(); @@ -268,10 +271,10 @@ BR_EXPORT const char *br_most_recent_message();
268 * \param abstractions Regular expression of the abstractions to search. 271 * \param abstractions Regular expression of the abstractions to search.
269 * \param implementations Regular expression of the implementations to search. 272 * \param implementations Regular expression of the implementations to search.
270 * \param parameters Include parameters after object name. 273 * \param parameters Include parameters after object name.
271 - * \note \ref managed_return_value 274 + * \note \ref input_string_buffer
272 * \note This function uses Qt's <a href="http://doc.qt.digia.com/stable/qregexp.html">QRegExp</a> syntax. 275 * \note This function uses Qt's <a href="http://doc.qt.digia.com/stable/qregexp.html">QRegExp</a> syntax.
273 */ 276 */
274 -BR_EXPORT const char *br_objects(const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true); 277 +BR_EXPORT int br_objects(char * buffer, int buffer_length, const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true);
275 278
276 /*! 279 /*!
277 * \brief Renders recognition performance figures for a set of <tt>.csv</tt> files created by \ref br_eval. 280 * \brief Renders recognition performance figures for a set of <tt>.csv</tt> files created by \ref br_eval.
@@ -376,14 +379,14 @@ BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv); @@ -376,14 +379,14 @@ BR_EXPORT void br_read_pipe(const char *pipe, int *argc, char ***argv);
376 379
377 /*! 380 /*!
378 * \brief Wraps br::Context::scratchPath() 381 * \brief Wraps br::Context::scratchPath()
379 - * \note \ref managed_return_value 382 + * \note \ref input_string_buffer
380 * \see br_version 383 * \see br_version
381 */ 384 */
382 -BR_EXPORT const char *br_scratch_path(); 385 +BR_EXPORT int br_scratch_path(char * buffer, int buffer_length);
  386 +
383 387
384 /*! 388 /*!
385 * \brief Returns the full path to the root of the SDK. 389 * \brief Returns the full path to the root of the SDK.
386 - * \note \ref managed_return_value  
387 * \see br_initialize 390 * \see br_initialize
388 */ 391 */
389 BR_EXPORT const char *br_sdk_path(); 392 BR_EXPORT const char *br_sdk_path();
@@ -436,7 +439,6 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode @@ -436,7 +439,6 @@ BR_EXPORT void br_train_n(int num_inputs, const char *inputs[], const char *mode
436 439
437 /*! 440 /*!
438 * \brief Wraps br::Context::version() 441 * \brief Wraps br::Context::version()
439 - * \note \ref managed_return_value  
440 * \see br_about br_scratch_path 442 * \see br_about br_scratch_path
441 */ 443 */
442 BR_EXPORT const char *br_version(); 444 BR_EXPORT const char *br_version();
@@ -508,16 +510,18 @@ BR_EXPORT int br_img_channels(br_template tmpl); @@ -508,16 +510,18 @@ BR_EXPORT int br_img_channels(br_template tmpl);
508 BR_EXPORT bool br_img_is_empty(br_template tmpl); 510 BR_EXPORT bool br_img_is_empty(br_template tmpl);
509 /*! 511 /*!
510 * \brief Get the filename for a br::Template 512 * \brief Get the filename for a br::Template
  513 + * \note \ref input_string_buffer
511 */ 514 */
512 -BR_EXPORT const char* br_get_filename(br_template tmpl); 515 +BR_EXPORT int br_get_filename(char * buffer, int buffer_length, br_template tmpl);
513 /*! 516 /*!
514 * \brief Set the filename for a br::Template. 517 * \brief Set the filename for a br::Template.
515 */ 518 */
516 BR_EXPORT void br_set_filename(br_template tmpl, const char *filename); 519 BR_EXPORT void br_set_filename(br_template tmpl, const char *filename);
517 /*! 520 /*!
518 * \brief Get metadata as a string for the given key in the given template. 521 * \brief Get metadata as a string for the given key in the given template.
  522 + * \note \ref input_string_buffer
519 */ 523 */
520 -BR_EXPORT const char* br_get_metadata_string(br_template, const char *key); 524 +BR_EXPORT int br_get_metadata_string(char * buffer, int buffer_length, br_template tmpl, const char *key);
521 /*! 525 /*!
522 * \brief Enroll a br::Template from the C API! Returns a pointer to a br::TemplateList 526 * \brief Enroll a br::Template from the C API! Returns a pointer to a br::TemplateList
523 * \param tmpl Pointer to a br::Template. 527 * \param tmpl Pointer to a br::Template.
openbr/openbr_plugin.cpp
@@ -203,6 +203,13 @@ QList&lt;QRectF&gt; File::namedRects() const @@ -203,6 +203,13 @@ QList&lt;QRectF&gt; File::namedRects() const
203 const QVariant &variant = m_metadata[key]; 203 const QVariant &variant = m_metadata[key];
204 if (variant.canConvert<QRectF>()) 204 if (variant.canConvert<QRectF>())
205 rects.append(variant.value<QRectF>()); 205 rects.append(variant.value<QRectF>());
  206 + else if(variant.canConvert<QList<QRectF> >()) {
  207 + QList<QRectF> list = variant.value<QList<QRectF> >();
  208 + for (int i=0;i < list.size();i++)
  209 + {
  210 + rects.append(list[i]);
  211 + }
  212 + }
206 } 213 }
207 return rects; 214 return rects;
208 } 215 }
@@ -1009,6 +1016,47 @@ QString br::Context::scratchPath() @@ -1009,6 +1016,47 @@ QString br::Context::scratchPath()
1009 return QString("%1/%2-%3.%4").arg(QDir::homePath(), PRODUCT_NAME, QString::number(PRODUCT_VERSION_MAJOR), QString::number(PRODUCT_VERSION_MINOR)); 1016 return QString("%1/%2-%3.%4").arg(QDir::homePath(), PRODUCT_NAME, QString::number(PRODUCT_VERSION_MAJOR), QString::number(PRODUCT_VERSION_MINOR));
1010 } 1017 }
1011 1018
  1019 +
  1020 +QStringList br::Context::objects(const char *abstractions, const char *implementations, bool parameters)
  1021 +{
  1022 + QStringList objectList;
  1023 + QRegExp abstractionsRegExp(abstractions);
  1024 + QRegExp implementationsRegExp(implementations);
  1025 +
  1026 + if (abstractionsRegExp.exactMatch("Abbreviation"))
  1027 + foreach (const QString &name, Globals->abbreviations.keys())
  1028 + if (implementationsRegExp.exactMatch(name))
  1029 + objectList.append(name + (parameters ? "\t" + Globals->abbreviations[name] : ""));
  1030 +
  1031 + if (abstractionsRegExp.exactMatch("Distance"))
  1032 + foreach (const QString &name, Factory<Distance>::names())
  1033 + if (implementationsRegExp.exactMatch(name))
  1034 + objectList.append(name + (parameters ? "\t" + Factory<Distance>::parameters(name) : ""));
  1035 +
  1036 + if (abstractionsRegExp.exactMatch("Format"))
  1037 + foreach (const QString &name, Factory<Format>::names())
  1038 + if (implementationsRegExp.exactMatch(name))
  1039 + objectList.append(name + (parameters ? "\t" + Factory<Format>::parameters(name) : ""));
  1040 +
  1041 + if (abstractionsRegExp.exactMatch("Initializer"))
  1042 + foreach (const QString &name, Factory<Initializer>::names())
  1043 + if (implementationsRegExp.exactMatch(name))
  1044 + objectList.append(name + (parameters ? "\t" + Factory<Initializer>::parameters(name) : ""));
  1045 +
  1046 + if (abstractionsRegExp.exactMatch("Output"))
  1047 + foreach (const QString &name, Factory<Output>::names())
  1048 + if (implementationsRegExp.exactMatch(name))
  1049 + objectList.append(name + (parameters ? "\t" + Factory<Output>::parameters(name) : ""));
  1050 +
  1051 + if (abstractionsRegExp.exactMatch("Transform"))
  1052 + foreach (const QString &name, Factory<Transform>::names())
  1053 + if (implementationsRegExp.exactMatch(name))
  1054 + objectList.append(name + (parameters ? "\t" + Factory<Transform>::parameters(name) : ""));
  1055 +
  1056 +
  1057 + return objectList;
  1058 +}
  1059 +
1012 void br::Context::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) 1060 void br::Context::messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
1013 { 1061 {
1014 // Something about this method is not thread safe, and will lead to crashes if qDebug 1062 // Something about this method is not thread safe, and will lead to crashes if qDebug
openbr/openbr_plugin.h
@@ -830,6 +830,18 @@ public: @@ -830,6 +830,18 @@ public:
830 */ 830 */
831 static QString scratchPath(); 831 static QString scratchPath();
832 832
  833 + /*!
  834 + * \brief Returns names and parameters for the requested objects.
  835 + *
  836 + * Each object is \c \\n seperated. Arguments are seperated from the object name with a \c \\t.
  837 + * \param abstractions Regular expression of the abstractions to search.
  838 + * \param implementations Regular expression of the implementations to search.
  839 + * \param parameters Include parameters after object name.
  840 + * \note \ref managed_return_value
  841 + * \note This function uses Qt's <a href="http://doc.qt.digia.com/stable/qregexp.html">QRegExp</a> syntax.
  842 + */
  843 + static QStringList objects(const char *abstractions = ".*", const char *implementations = ".*", bool parameters = true);
  844 +
833 private: 845 private:
834 static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); 846 static void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
835 }; 847 };
scripts/brpy/__init__.py
@@ -12,6 +12,14 @@ def _var_string_args(n): @@ -12,6 +12,14 @@ def _var_string_args(n):
12 s.extend(_string_args(n)) 12 s.extend(_string_args(n))
13 return s 13 return s
14 14
  15 +def _handle_string_func(func):
  16 + def call_func(*args):
  17 + howlong = func('', 0, *args)
  18 + msg = 'x'*(howlong-1)
  19 + func(msg, howlong, *args)
  20 + return msg
  21 + return call_func
  22 +
15 def init_brpy(br_loc='/usr/local/lib'): 23 def init_brpy(br_loc='/usr/local/lib'):
16 """Takes the ctypes lib object for br and initializes all function inputs and outputs""" 24 """Takes the ctypes lib object for br and initializes all function inputs and outputs"""
17 br_loc += '/libopenbr.%s' 25 br_loc += '/libopenbr.%s'
@@ -48,9 +56,14 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;): @@ -48,9 +56,14 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;):
48 br.br_is_classifier.restype = c_bool 56 br.br_is_classifier.restype = c_bool
49 br.br_make_mask.argtypes = _string_args(3) 57 br.br_make_mask.argtypes = _string_args(3)
50 br.br_make_pairwise_mask.argtypes = _string_args(3) 58 br.br_make_pairwise_mask.argtypes = _string_args(3)
51 - br.br_most_recent_message.restype = c_char_p  
52 - br.br_objects.argtypes = _string_args(2) + [c_bool]  
53 - br.br_objects.restype = c_char_p 59 + br.br_most_recent_message.argtypes = [c_char_p, c_int]
  60 + br.br_most_recent_message.restype = c_int
  61 + func = br.br_most_recent_message.__call__
  62 + br.br_most_recent_message = _handle_string_func(func)
  63 + br.br_objects.argtypes = [c_char_p, c_int] + _string_args(2) + [c_bool]
  64 + br.br_objects.restype = c_int
  65 + func2 = br.br_objects.__call__
  66 + br.br_objects = _handle_string_func(func2)
54 br.br_plot.argtypes = plot_args 67 br.br_plot.argtypes = plot_args
55 br.br_plot.restype = c_bool 68 br.br_plot.restype = c_bool
56 br.br_plot_detection.argtypes = plot_args 69 br.br_plot_detection.argtypes = plot_args
@@ -61,7 +74,10 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;): @@ -61,7 +74,10 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;):
61 br.br_plot_metadata.restype = c_bool 74 br.br_plot_metadata.restype = c_bool
62 br.br_progress.restype = c_float 75 br.br_progress.restype = c_float
63 br.br_read_pipe.argtypes = [c_char_p, POINTER(c_int), POINTER(POINTER(c_char_p))] 76 br.br_read_pipe.argtypes = [c_char_p, POINTER(c_int), POINTER(POINTER(c_char_p))]
64 - br.br_scratch_path.restype = c_char_p 77 + br.br_scratch_path.argtypes = [c_char_p, c_int]
  78 + br.br_scratch_path.restype = c_int
  79 + func3 = br.br_scratch_path.__call__
  80 + br.br_scratch_path = _handle_string_func(func3)
65 br.br_sdk_path.restype = c_char_p 81 br.br_sdk_path.restype = c_char_p
66 br.br_get_header.argtypes = [c_char_p, POINTER(c_char_p), POINTER(c_char_p)] 82 br.br_get_header.argtypes = [c_char_p, POINTER(c_char_p), POINTER(c_char_p)]
67 br.br_set_header.argtypes = _string_args(3) 83 br.br_set_header.argtypes = _string_args(3)
@@ -88,11 +104,15 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;): @@ -88,11 +104,15 @@ def init_brpy(br_loc=&#39;/usr/local/lib&#39;):
88 br.br_img_channels.restype = c_int 104 br.br_img_channels.restype = c_int
89 br.br_img_is_empty.argtypes = [c_void_p] 105 br.br_img_is_empty.argtypes = [c_void_p]
90 br.br_img_is_empty.restype = c_bool 106 br.br_img_is_empty.restype = c_bool
91 - br.br_get_filename.argtypes = [c_void_p]  
92 - br.br_get_filename.restype = c_char_p 107 + br.br_get_filename.argtypes = [c_char_p, c_int, c_void_p]
  108 + br.br_get_filename.restype = c_int
  109 + func4 = br.br_get_filename.__call__
  110 + br.br_get_filename = _handle_string_func(func4)
93 br.br_set_filename.argtypes = [c_void_p, c_char_p] 111 br.br_set_filename.argtypes = [c_void_p, c_char_p]
94 - br.br_get_metadata_string.argtypes = [c_void_p, c_char_p]  
95 - br.br_get_metadata_string.restype = c_char_p 112 + br.br_get_metadata_string.argtypes = [c_char_p, c_int, c_void_p, c_char_p]
  113 + br.br_get_metadata_string.restype = c_int
  114 + func5 = br.br_get_metadata_string.__call__
  115 + br.br_get_metadata_string = _handle_string_func(func5)
96 br.br_enroll_template.argtypes = [c_void_p] 116 br.br_enroll_template.argtypes = [c_void_p]
97 br.br_enroll_template.restype = c_void_p 117 br.br_enroll_template.restype = c_void_p
98 br.br_enroll_template_list.argtypes = [c_void_p] 118 br.br_enroll_template_list.argtypes = [c_void_p]