diff --git a/modules/matlab/CMakeLists.txt b/modules/matlab/CMakeLists.txt
index 261dcf259e..fc397e4658 100644
--- a/modules/matlab/CMakeLists.txt
+++ b/modules/matlab/CMakeLists.txt
@@ -34,20 +34,29 @@ macro(PREPEND TOKEN OUT IN)
endforeach()
endmacro()
+
# WARN_MIXED_PRECISION
# Formats a warning message if the compiler and Matlab bitness is different
macro(WARN_MIXED_PRECISION COMPILER_BITNESS MATLAB_BITNESS)
set(MSG "Your compiler is ${COMPILER_BITNESS}-bit")
set(MSG "${MSG} but your version of Matlab is ${MATLAB_BITNESS}-bit.")
- set(MSG "${MSG} Mixed preicision pointers are not supported. Disabling Matlab bindings...")
+ set(MSG "${MSG} To build Matlab bindings, please switch to a ${MATLAB_BITNESS}-bit compiler.")
message(WARNING ${MSG})
endmacro()
+# ----------------------------------------------------------------------------
+# Architecture checks
+# ----------------------------------------------------------------------------
# make sure we're on a supported architecture with Matlab and python installed
-if (IOS OR ANDROID OR NOT MATLAB_FOUND OR NOT PYTHONLIBS_FOUND)
+if (IOS OR ANDROID OR NOT MATLAB_FOUND)
+ ocv_module_disable(matlab)
+ return()
+elseif (NOT PYTHONLIBS_FOUND)
+ message(WARNING "A required dependency of the matlab module (PythonLibs) was not found. Disabling Matlab bindings...")
ocv_module_disable(matlab)
return()
endif()
+
# If the user built OpenCV as X-bit, but they have a Y-bit version of Matlab,
# attempting to link to OpenCV during binding generation will fail, since
@@ -63,6 +72,16 @@ elseif (${ARCH} EQUAL 64 AND NOT ${MATLAB_ARCH} MATCHES "64")
return()
endif()
+# If it's MSVC, warn the user that bindings will only be built in Release mode.
+# Debug mode seems to cause issues...
+if (MSVC)
+ message(STATUS "Warning: Matlab bindings will only be built in Release configurations")
+endif()
+
+
+# ----------------------------------------------------------------------------
+# Configure time components
+# ----------------------------------------------------------------------------
set(the_description "The Matlab/Octave bindings")
ocv_add_module(matlab BINDINGS
OPTIONAL opencv_core
@@ -93,9 +112,9 @@ endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
-# ----------------------------------------------------------------------------
-# Configure time components
-# ----------------------------------------------------------------------------
+# intersection of available modules and optional dependencies
+# 1. populate the command-line include directories (-I/path/to/module/header, ...)
+# 2. populate the command-line link libraries (-lopencv_core, ...) for Debug and Release
set(MATLAB_DEPS ${OPENCV_MODULE_${the_module}_REQ_DEPS} ${OPENCV_MODULE_${the_module}_OPT_DEPS})
foreach(opencv_module ${MATLAB_DEPS})
if (HAVE_${opencv_module})
@@ -114,7 +133,7 @@ list(APPEND opencv_extra_hdrs "core=${OPENCV_MODULE_opencv_core_LOCATION}/includ
# pass the OPENCV_CXX_EXTRA_FLAGS through to the mex compiler
# remove the visibility modifiers, so the mex gateway is visible
# TODO: get mex working without warnings
-#string(REGEX REPLACE "[^\ ]*visibility[^\ ]*" "" MEX_CXXFLAGS "${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_CXX_FLAGS}")
+string(REGEX REPLACE "[^\ ]*visibility[^\ ]*" "" MEX_CXXFLAGS "${OPENCV_EXTRA_FLAGS} ${OPENCV_EXTRA_CXX_FLAGS}")
# Configure checks
# Check to see whether the generator and the mex compiler are working.
@@ -149,7 +168,7 @@ if (NOT MEX_WORKS)
# attempt to compile a gateway using mex
message(STATUS "Trying to compile mex file")
execute_process(
- COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_OPTS} "CXXFLAGS=\$CXXFLAGS ${MEX_CXXFLAGS}"
+ COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_OPTS} "CXXFLAGS=\$CXXFLAGS ${MEX_CXX_FLAGS}"
${MEX_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/test/test_compiler.cpp
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/junk
ERROR_VARIABLE MEX_ERROR
@@ -208,6 +227,14 @@ add_custom_command(
--modules ${opencv_modules}
--configuration "$(Configuration)" ${CMAKE_BUILD_TYPE}
--outdir ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${PYTHON_EXECUTABLE}
+ ${CMAKE_CURRENT_SOURCE_DIR}/generator/cvmex.py
+ --opts="${MEX_OPTS}"
+ --include_dirs="${MEX_INCLUDE_DIRS}"
+ --lib_dir=${MEX_LIB_DIR}
+ --libs="${MEX_LIBS}"
+ --flags ${MEX_CXXFLAGS}
+ --outdir ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/test/help.m ${CMAKE_CURRENT_BINARY_DIR}/+cv
COMMAND ${CMAKE_COMMAND} -E touch ${GENERATE_PROXY}
COMMENT "Generating Matlab source files"
@@ -222,7 +249,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -DMATLAB_MEX_SCRIPT=${MATLAB_MEX_SCRIPT}
-DMATLAB_MEXEXT=${MATLAB_MEXEXT}
-DMEX_OPTS=${MEX_OPTS}
- -DMEX_CXXFLAGS=${MEX_CXXFLAGS}
+ -DMEX_CXXFLAGS=${MEX_CXX_FLAGS}
-DMEX_INCLUDE_DIRS="${MEX_INCLUDE_DIRS}"
-DMEX_LIB_DIR=${MEX_LIB_DIR}
-DCONFIGURATION="$(Configuration)"
diff --git a/modules/matlab/compile.cmake b/modules/matlab/compile.cmake
index fd4ebd483c..ebc3fd9a68 100644
--- a/modules/matlab/compile.cmake
+++ b/modules/matlab/compile.cmake
@@ -1,7 +1,12 @@
+# LISTIFY
+# Given a string of space-delimited tokens, reparse as a string of
+# semi-colon delimited tokens, which in CMake land is exactly equivalent
+# to a list
macro(listify OUT_LIST IN_STRING)
string(REPLACE " " ";" ${OUT_LIST} ${IN_STRING})
endmacro()
+# listify multiple-argument inputs
listify(MEX_INCLUDE_DIRS_LIST ${MEX_INCLUDE_DIRS})
if (${CONFIGURATION} MATCHES "Debug")
listify(MEX_LIBS_LIST ${MEX_DEBUG_LIBS})
@@ -9,11 +14,22 @@ else()
listify(MEX_LIBS_LIST ${MEX_LIBS})
endif()
+# if it's MSVC building a Debug configuration, don't build bindings
+if ("${CONFIGURATION}" MATCHES "Debug")
+ message(STATUS "Matlab bindings are only available in Release configurations. Skipping...")
+ return()
+endif()
+
+# for each generated source file:
+# 1. check if the file has already been compiled
+# 2. attempt compile if required
+# 3. if the compile fails, throw an error and cancel compilation
file(GLOB SOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/src/*.cpp")
foreach(SOURCE_FILE ${SOURCE_FILES})
# strip out the filename
get_filename_component(FILENAME ${SOURCE_FILE} NAME_WE)
- # compie the source file using mex
+ # compile the source file using mex
+ execute_process(COMMAND echo ${FILENAME})
if (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/+cv/${FILENAME}.${MATLAB_MEXEXT})
execute_process(
COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_OPTS} "CXXFLAGS=\$CXXFLAGS ${MEX_CXXFLAGS}" ${MEX_INCLUDE_DIRS_LIST}
diff --git a/modules/matlab/generator/build_info.py b/modules/matlab/generator/build_info.py
index 50d3ffe452..beb91bd108 100644
--- a/modules/matlab/generator/build_info.py
+++ b/modules/matlab/generator/build_info.py
@@ -19,7 +19,7 @@ def substitute(build, output_dir):
os.mkdir(output_dir)
# populate template
- populated = template.render(build=build)
+ populated = template.render(build=build, time=time)
with open(os.path.join(output_dir, 'buildInformation.m'), 'wb') as f:
f.write(populated)
@@ -46,7 +46,7 @@ if __name__ == "__main__":
"""
# parse the input options
- import sys, re, os
+ import sys, re, os, time
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('--os')
diff --git a/modules/matlab/generator/cvmex.py b/modules/matlab/generator/cvmex.py
new file mode 100644
index 0000000000..fc47100e17
--- /dev/null
+++ b/modules/matlab/generator/cvmex.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+def substitute(cv, output_dir):
+
+ # setup the template engine
+ template_dir = os.path.join(os.path.dirname(__file__), 'templates')
+ jtemplate = Environment(loader=FileSystemLoader(template_dir), trim_blocks=True, lstrip_blocks=True)
+
+ # add the filters
+ jtemplate.filters['cellarray'] = cellarray
+ jtemplate.filters['split'] = split
+ jtemplate.filters['csv'] = csv
+
+ # load the template
+ template = jtemplate.get_template('template_cvmex_base.m')
+
+ # create the build directory
+ output_dir = output_dir+'/+cv'
+ if not os.path.isdir(output_dir):
+ os.mkdir(output_dir)
+
+ # populate template
+ populated = template.render(cv=cv, time=time)
+ with open(os.path.join(output_dir, 'mex.m'), 'wb') as f:
+ f.write(populated)
+
+if __name__ == "__main__":
+ """
+ Usage: python cvmex.py --opts [-list -of -opts]
+ --include_dirs [-list -of -opencv_include_directories]
+ --lib_dir opencv_lib_directory
+ --libs [-lopencv_core -lopencv_imgproc ...]
+ --flags [-Wall -opencv_build_flags ...]
+ --outdir /path/to/generated/output
+
+ cvmex.py generates a custom mex compiler that automatically links OpenCV
+ libraries to built sources where appropriate. The calling syntax is the
+ same as the builtin mex compiler, with added cv qualification:
+ >> cv.mex(..., ...);
+ """
+
+ # parse the input options
+ import sys, re, os, time
+ from argparse import ArgumentParser
+ parser = ArgumentParser()
+ parser.add_argument('--opts')
+ parser.add_argument('--include_dirs')
+ parser.add_argument('--lib_dir')
+ parser.add_argument('--libs')
+ parser.add_argument('--flags')
+ parser.add_argument('--outdir')
+ cv = parser.parse_args()
+
+ from filters import *
+ from jinja2 import Environment, FileSystemLoader
+
+ # populate the mex base template
+ substitute(cv, cv.outdir)
diff --git a/modules/matlab/generator/filters.py b/modules/matlab/generator/filters.py
index e908fe8ff4..f2d59b2b0c 100644
--- a/modules/matlab/generator/filters.py
+++ b/modules/matlab/generator/filters.py
@@ -139,10 +139,18 @@ def filename(fullpath):
'''
return os.path.splitext(os.path.basename(fullpath))[0]
+def split(text, delimiter=' '):
+ '''Split a text string into a list using the specified delimiter'''
+ return text.split(delimiter)
+
def csv(items, sep=', '):
'''format a list with a separator (comma if not specified)'''
return sep.join(item for item in items)
+def cellarray(items, escape='\''):
+ '''format a list of items as a matlab cell array'''
+ return '{' + ', '.join(escape+item+escape for item in items) + '}'
+
def stripExtraSpaces(text):
'''Removes superfluous whitespace from a string, including the removal
of all leading and trailing whitespace'''
diff --git a/modules/matlab/generator/templates/template_build_info.m b/modules/matlab/generator/templates/template_build_info.m
index 486e0a03d0..1d9124af2f 100644
--- a/modules/matlab/generator/templates/template_build_info.m
+++ b/modules/matlab/generator/templates/template_build_info.m
@@ -6,6 +6,8 @@ function buildInformation()
% run into issues with the Toolbox, it is useful to submit this
% information alongside a bug report to the OpenCV team.
%
+% Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation
+%
info = {
' ------------------------------------------------------------------------'
' OpenCV Toolbox'
diff --git a/modules/matlab/generator/templates/template_cvmex_base.m b/modules/matlab/generator/templates/template_cvmex_base.m
new file mode 100644
index 0000000000..8ec6cf5151
--- /dev/null
+++ b/modules/matlab/generator/templates/template_cvmex_base.m
@@ -0,0 +1,46 @@
+function mex(varargin)
+%CV.MEX compile MEX-function with OpenCV linkages
+%
+% Usage:
+% CV.MEX [options ...] file [file file ...]
+%
+% Description:
+% CV.MEX compiles one or more C/C++ source files into a shared-library
+% called a mex-file. This function is equivalent to the builtin MEX
+% routine, with the notable exception that it automatically resolves
+% OpenCV includes, and links in the OpenCV libraries where appropriate.
+% It also forwards the flags used to build OpenCV, so architecture-
+% specific optimizations can be used.
+%
+% CV.MEX is designed to be used in situations where the source(s) you
+% are compiling contain OpenCV definitions. In such cases, it streamlines
+% the finding and including of appropriate OpenCV libraries.
+%
+% See also: mex
+%
+% Copyright {{ time.strftime("%Y", time.localtime()) }} The OpenCV Foundation
+%
+
+ % forward the OpenCV build flags (C++ only)
+ EXTRA_FLAGS = ['"CXXFLAGS="\$CXXFLAGS '...
+ '{{ cv.flags | trim | wordwrap(60, false, '\'...\n \'') }}""'];
+
+ % add the OpenCV include dirs
+ INCLUDE_DIRS = {{ cv.include_dirs | split | cellarray | wordwrap(60, false, '...\n ') }};
+
+ % add the lib dir (singular in both build tree and install tree)
+ LIB_DIR = '{{ cv.lib_dir }}';
+
+ % add the OpenCV libs. Only the used libs will actually be linked
+ LIBS = {{ cv.libs | split | cellarray | wordwrap(60, false, '...\n ') }};
+
+ % add the mex opts (usually at least -largeArrayDims)
+ OPTS = {{ cv.opts | split | cellarray | wordwrap(60, false, '...\n ') }};
+
+ % merge all of the default options (EXTRA_FLAGS, LIBS, etc) and the options
+ % and files passed by the user (varargin) into a single cell array
+ merged = [ {EXTRA_FLAGS}, INCLUDE_DIRS, {LIB_DIR}, LIBS, OPTS, varargin ];
+
+ % expand the merged argument list into the builtin mex utility
+ mex(merged{:});
+end
diff --git a/modules/matlab/include/mxarray.hpp b/modules/matlab/include/mxarray.hpp
index a2c10199a5..1c34255f99 100644
--- a/modules/matlab/include/mxarray.hpp
+++ b/modules/matlab/include/mxarray.hpp
@@ -2,9 +2,19 @@
#define OPENCV_MXARRAY_HPP_
#include
+#include
#include
#include
+#include
+#include
#include
+#if __cplusplus > 201103
+#include
+typedef std::unordered_set StringSet;
+#else
+#include
+typedef std::set StringSet;
+#endif
#include "mex.h"
#include "transpose.hpp"
@@ -274,10 +284,10 @@ public:
* Explicitly construct a scalar of given type. Since constructors cannot
* be explicitly templated, this is a static factory method
*/
- template
- static MxArray Scalar(Scalar value = 0) {
- MxArray s(1, 1, 1, Matlab::Traits::ScalarType);
- s.real()[0] = value;
+ template
+ static MxArray Scalar(ScalarType value = 0) {
+ MxArray s(1, 1, 1, Matlab::Traits::ScalarType);
+ s.real()[0] = value;
return s;
}
@@ -410,8 +420,8 @@ public:
std::string toString() const {
conditionalError(isString(), "Attempted to convert non-string type to string");
- std::string str(size()+1, '\0');
- mxGetString(ptr_, const_cast(str.data()), str.size());
+ std::string str(size(), '\0');
+ mxGetString(ptr_, const_cast(str.data()), str.size()+1);
return str;
}
@@ -432,6 +442,214 @@ public:
};
+/*! @class ArgumentParser
+ * @brief parses inputs to a method and resolves the argument names.
+ *
+ * The ArgumentParser resolves the inputs to a method. It checks that all
+ * required arguments are specified and also allows named optional arguments.
+ * For example, the C++ function:
+ * void randn(Mat& mat, Mat& mean=Mat(), Mat& std=Mat());
+ * could be called in Matlab using any of the following signatures:
+ * \code
+ * out = randn(in);
+ * out = randn(in, 0, 1);
+ * out = randn(in, 'mean', 0, 'std', 1);
+ * \endcode
+ *
+ * ArgumentParser also enables function overloading by allowing users
+ * to add variants to a method. For example, there may be two C++ sum() methods:
+ * \code
+ * double sum(Mat& mat); % sum elements of a matrix
+ * Mat sum(Mat& A, Mat& B); % add two matrices
+ * \endcode
+ *
+ * by adding two variants to ArgumentParser, the correct underlying sum
+ * method can be called. If the function call is ambiguous, the
+ * ArgumentParser will fail with an error message.
+ *
+ * The previous example could be parsed as:
+ * \code
+ * // set up the Argument parser
+ * ArgumentParser arguments;
+ * arguments.addVariant("elementwise", 1);
+ * arguments.addVariant("matrix", 2);
+ *
+ * // parse the arguments
+ * std::vector inputs;
+ * inputs = arguments.parse(std::vector(prhs, prhs+nrhs));
+ *
+ * // if we get here, one unique variant is valid
+ * if (arguments.variantIs("elementwise")) {
+ * // call elementwise sum()
+ * }
+ */
+class ArgumentParser {
+private:
+ struct Variant;
+ typedef std::string String;
+ typedef std::vector StringVector;
+ typedef std::vector MxArrayVector;
+ typedef std::vector VariantVector;
+ /* @class Variant
+ * @brief Describes a variant of arguments to a method
+ *
+ * When addVariant() is called on an instance to ArgumentParser, this class
+ * holds the the information that decribes that variant. The parse() method
+ * of ArgumentParser then attempts to match a Variant, given a set of
+ * inputs for a method invocation.
+ */
+ class Variant {
+ public:
+ Variant(const String& _name, size_t _nreq, size_t _nopt, const StringVector& _keys)
+ : name(_name), nreq(_nreq), nopt(_nopt), keys(_keys), using_named(false) {}
+ String name;
+ size_t nreq;
+ size_t nopt;
+ StringVector keys;
+ bool using_named;
+ /*! @brief return true if the named-argument is in the Variant */
+ bool count(const String& key) { return std::find(keys.begin(), keys.end(), key) != keys.end(); }
+ /*! @brief remove a key by index from the Variant */
+ void erase(const size_t idx) { keys.erase(keys.begin()+idx); }
+ /*! @brief remove a key by name from the Variant */
+ void erase(const String& key) { keys.erase(std::find(keys.begin(), keys.end(), key)); }
+ /*! @brief convert a Variant to a string representation */
+ String toString(const String& method_name=String("f")) const {
+ std::ostringstream s;
+ s << method_name << "(";
+ for (size_t n = 0; n < nreq; ++n) {
+ s << "src" << n+1; if (n != nreq-1) s << ", ";
+ }
+ if (nreq && nopt) s << ", ";
+ for (size_t n = 0; n < keys.size(); ++n) {
+ s << "'" << keys[n] << "', " << keys[n];
+ if (n != keys.size()-1) s << ", ";
+ }
+ s << ");";
+ return s.str();
+ }
+ };
+ MxArrayVector filled_;
+ VariantVector variants_;
+ String valid_;
+ String method_name_;
+public:
+ ArgumentParser(const String& method_name) : method_name_(method_name) {}
+ /*! @brief add a function call variant to the parser
+ *
+ * Adds a function-call signature to the parser. The function call *must* be
+ * unique either in its number of arguments, or in the named-syntax.
+ * Currently this function does not check whether that invariant stands true.
+ *
+ * This function is variadic. If should be called as follows:
+ * addVariant(2, 2, 'opt_1_name', 'opt_2_name');
+ */
+ void addVariant(const String& name, size_t nreq, size_t nopt = 0, ...) {
+ StringVector keys;
+ va_list opt;
+ va_start(opt, nopt);
+ for (size_t n = 0; n < nopt; ++n) keys.push_back(va_arg(opt, const char*));
+ addVariant(name, nreq, nopt, keys);
+ }
+ void addVariant(const String& name, size_t nreq, size_t nopt, StringVector keys) {
+ variants_.push_back(Variant(name, nreq, nopt, keys));
+ }
+ /*! @brief check if the valid variant is the key name */
+ bool variantIs(const String& name) {
+ return name.compare(valid_) == 0;
+ }
+ /*! @brief parse a vector of input arguments
+ *
+ * This method parses a vector of input arguments, attempting to match them
+ * to a Variant spec. For each input, the method attempts to cull any
+ * Variants which don't match the given inputs so far.
+ *
+ * Once all inputs have been parsed, if there is one unique spec remaining,
+ * the output MxArray vector gets populated with the arguments, with named
+ * arguments removed. Any optional arguments that have not been encountered
+ * are set to an empty array.
+ *
+ * If multiple variants or no variants match the given call, an error
+ * message is emitted
+ */
+ MxArrayVector parse(const MxArrayVector& inputs) {
+ // allocate the outputs
+ MxArrayVector outputs;
+ VariantVector candidates = variants_;
+
+ // iterate over the inputs, attempting to match a variant
+ for (MxArrayVector::const_iterator input = inputs.begin(); input != inputs.end(); ++input) {
+ String name = input->isString() ? input->toString() : String();
+ for (VariantVector::iterator candidate = candidates.begin(); candidate < candidates.end(); ++candidate) {
+ // check if the input is a key
+ bool key = candidate->count(name);
+
+ /*
+ * FAILURE CASES
+ * 1. too many inputs, or
+ * 2. name is not a key and we're expecting a key
+ * 3. name is a key, and
+ * we're still expecting required arguments, or
+ * we're expecting an argument for a previous key
+ */
+ if ((!candidate->nreq && !candidate->nopt) ||
+ (!key && !candidate->nreq && candidate->keys.size() == candidate->nopt && candidate->using_named) ||
+ (key && (candidate->nreq || candidate->keys.size() < candidate->nopt))) {
+ candidate = candidates.erase(candidate)--;
+ }
+
+ // VALID CASES
+ // Still parsing required argments (input is not a key)
+ else if (!key && candidate->nreq) {
+ candidate->nreq--;
+ }
+
+ // Parsing optional arguments and a named argument is encountered
+ else if (key && !candidate->nreq && candidate->nopt > 0 && candidate->keys.size() == candidate->nopt) {
+ candidate->erase(name);
+ candidate->using_named = true;
+ }
+
+ // Parsing input for a named argument
+ else if (!key && candidate->keys.size() < candidate->nopt) {
+ candidate->nopt--;
+ }
+
+ // Parsing un-named optional arguments
+ else if (!key && !candidate->nreq && candidate->nopt && candidate->keys.size() && !candidate->using_named) {
+ candidate->erase(0);
+ candidate->nopt--;
+ }
+ }
+ }
+
+ // if any candidates remain, check that they have been fully parsed
+ for (VariantVector::iterator candidate = candidates.begin(); candidate < candidates.end(); ++candidate) {
+ if (candidate->nreq || candidate->keys.size() < candidate->nopt) {
+ candidate = candidates.erase(candidate)--;
+ }
+ }
+
+ // if there is not a unique candidate, throw an error
+ String variant_string;
+ for (VariantVector::iterator variant = variants_.begin(); variant != variants_.end(); ++variant) {
+ variant_string += "\n" + variant->toString(method_name_);
+ }
+
+ // if there is not a unique candidate, throw an error
+ if (candidates.size() > 1) {
+ error(String("Call to method is ambiguous. Valid variants are:")
+ .append(variant_string).append("\nUse named arguments to disambiguate call"));
+ }
+ if (candidates.size() == 0) {
+ error(String("No matching method signatures for given arguments. Valid variants are:").append(variant_string));
+ }
+
+ return outputs;
+ }
+};
+
+
/*!
* @brief template specialization for inheriting types
*
diff --git a/modules/matlab/test/cv_exception.cpp b/modules/matlab/test/cv_exception.cpp
index 9ae530f2b2..4f63c1e08d 100644
--- a/modules/matlab/test/cv_exception.cpp
+++ b/modules/matlab/test/cv_exception.cpp
@@ -7,7 +7,7 @@
* Copyright 2013 The OpenCV Foundation
*/
#include
-//#include
+#include
#include "mex.h"
/*
@@ -24,9 +24,9 @@ void mexFunction(int nlhs, mxArray* plhs[],
// call the opencv function
// [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn);
try {
- // throw cv::exception;
- //} catch(cv::exception& e) {
- // mexErrMsgTxt(e.what());
+ throw cv::Exception(-1, "OpenCV exception thrown", __func__, __FILE__, __LINE__);
+ } catch(cv::Exception& e) {
+ mexErrMsgTxt(e.what());
} catch(...) {
mexErrMsgTxt("Incorrect exception caught!");
}