Improved configure time tests. Added OpenCV specific exception handling
authorhbristow <hilton.bristow@gmail.com>
Wed, 19 Jun 2013 01:54:14 +0000 (11:54 +1000)
committerhbristow <hilton.bristow@gmail.com>
Wed, 19 Jun 2013 01:54:14 +0000 (11:54 +1000)
cmake/OpenCVFindMatlab.cmake
modules/matlab/CMakeLists.txt
modules/matlab/generator/templates/template_class_base.cpp
modules/matlab/generator/templates/template_function_base.cpp
modules/matlab/test/test_compiler.cpp [new file with mode: 0644]
modules/matlab/test/test_generator.hpp [moved from modules/matlab/test/rand.hpp with 69% similarity]

index 96cddcc..a66c21e 100644 (file)
@@ -6,14 +6,14 @@
 #
 #   MATLAB_FOUND:       true/false
 #   MATLAB_ROOT_DIR:    Root of Matlab installation
-#   MATLAB_MEX_SCRIPT   The mex script used to compile mex files
-#   MATLAB_INCLUDE_DIR  Path to "mex.h"
-#   MATLAB_LIBRARY_DIR  Path to mex and matrix libraries
-#   MATLAB_LIBS         The Matlab libs, usually mx, mex, mat
-#   MATLAB_MEXEXT       The mex library extension. It will be one of:
+#   MATLAB_MEX_SCRIPT:  The mex script used to compile mex files
+#   MATLAB_INCLUDE_DIR: Path to "mex.h"
+#   MATLAB_LIBRARY_DIR: Path to mex and matrix libraries
+#   MATLAB_LIBS:        The Matlab libs, usually mx, mex, mat
+#   MATLAB_MEXEXT:      The mex library extension. It will be one of:
 #                         mexwin32, mexwin64,  mexglx, mexa64, mexmac, 
 #                         mexmaci,  mexmaci64, mexsol, mexs64
-#   MATLAB_ARCH         The installation architecture. It is simply
+#   MATLAB_ARCH:        The installation architecture. It is simply
 #                       the MEXEXT with the preceding "mex" removed
 #
 # There doesn't appear to be an elegant way to detect all versions of Matlab
index 38eed60..3a4c306 100644 (file)
@@ -1,10 +1,36 @@
 # ----------------------------------------------------------------------------
 #  CMake file for Matlab/Octave support
+#
+#  Matlab code generation and compilation is broken down into two distinct
+#  stages: configure time and build time. The idea is that we want to give
+#  the user reasonable guarantees that once they type 'make' wrapper
+#  generation is unlikely to fail. Therefore we run a series of tests at
+#  configure time to check the working status of the core components.
+#
+#  Configure Time
+#  During configure time, the script attempts to ascertain whether the
+#  generator and mex compiler are working for a given architecture.
+#  Currently this involves:
+#   1) Generating a simple CV_EXPORTS_W symbol and checking whether a file
+#      of the symbol name is generated
+#   2) Compiling a simple mex gateway to check that Bridge.hpp and mex.h
+#      can be found, and that a file with the mexext is produced
+#
+#  Build Time
+#  If the configure time tests pass, then we assume Matlab wrapper generation
+#  will not fail during build time. We simply glob all of the symbols in
+#  the OpenCV module headers, generate intermediate .cpp files, then compile
+#  them with mex.
 # ----------------------------------------------------------------------------
+
+# PREPEND
+# Given a list of strings IN and a TOKEN, prepend the token to each string
+# and append to OUT. This is used for passing command line "-I", "-L" and "-l"
+# arguments to mex. e.g.
+# prepend("-I" OUT /path/to/include/dir) --> -I/path/to/include/dir
 macro(PREPEND TOKEN OUT IN)
     foreach(VAR ${IN})
-        string(REGEX REPLACE "^/" "${TOKEN}/" TMP ${VAR})
-        list(APPEND ${OUT} ${TMP})
+        list(APPEND ${OUT} "${TOKEN}${VAR}")
     endforeach()
 endmacro()
 
@@ -32,14 +58,14 @@ prepend("-I" MEX_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include)
 message("-- Trying to generate Matlab code")
 execute_process(
     COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab_caller.py 
-            ${CMAKE_CURRENT_SOURCE_DIR}/test/rand.hpp ${CMAKE_CURRENT_BINARY_DIR}
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/test_generator.hpp ${CMAKE_CURRENT_BINARY_DIR}
     ERROR_VARIABLE GEN_ERROR
     OUTPUT_QUIET 
 )
 
 if (GEN_ERROR)
     message(${GEN_ERROR})
-    message("-- Generating Matlab code failed. Disabling Matlab bindings...")
+    message("-- Error generating Matlab code. Disabling Matlab bindings...")
     # restore the pythonpath
     set(ENV{PYTHONPATH} ${PYPATH_CACHE})
     return()
@@ -50,7 +76,8 @@ endif()
 # attempt to compile the file using mex
 message("-- Trying to compile mex file")
 execute_process(
-    COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}/src/rand.cpp
+    COMMAND ${MATLAB_MEX_SCRIPT} ${MEX_INCLUDES} 
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/test_compiler.cpp
     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src
     ERROR_VARIABLE MEX_ERROR
     OUTPUT_QUIET
@@ -68,17 +95,20 @@ endif()
 
 # if we make it here, mex works!
 set_property(GLOBAL PROPERTY MEX_WORKS TRUE)
+return()
 
 # ----------------------------------------------------------------------------
 #  Build time components
 # ----------------------------------------------------------------------------
-#string(REPLACE "opencv_" "" OPENCV_MATLAB_MODULES "${OPENCV_MODULE_${the_module}_REQ_DEPS};
-#                                                   ${OPENCV_MODULE_${the_module}_OPT_DEPS}")
+string(REPLACE "opencv_" "" OPENCV_MATLAB_MODULES "${OPENCV_MODULE_${the_module}_REQ_DEPS};
+                                                   ${OPENCV_MODULE_${the_module}_OPT_DEPS}")
 foreach(module ${OPENCV_MATLAB_MODULES})
     if (HAVE_opencv_${module})
         list(APPEND opencv_hdrs "${OPENCV_MODULE_opencv_${module}_LOCATION}/include/opencv2/${module}.hpp")
+        prepend("-I" MEX_INCLUDES "${OPENCV_MODULE_opencv_${module}_LOCATION}/include")
     endif()
 endforeach()
+message(${MEX_INCLUDES})
 
 # synthesise the matlab sources
 # TODO:These should be build-time (ie add_custom_command)
index 655d157..3f8d251 100644 (file)
@@ -12,6 +12,7 @@
 #include <vector>
 #include <unordered_map>
 #include <string>
+#include <opencv2/core.hpp>
 {% block includes %}
 {% endblock %}
 
index 842bb3b..9e6e450 100644 (file)
@@ -9,7 +9,9 @@
  */
 #include "mex.h"
 #include "bridge.hpp"
+#include <string>
 #include <vector>
+#include <opencv2/core.hpp>
 {% block includes %}
 {% endblock %}
 
@@ -39,6 +41,8 @@ void mexFunction(int nlhs, mxArray* plhs[],
   // [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn);
   try {
     {{fun.name}}();
+  } catch(cv::Exception& e) {
+    mexErrMsgTxt(std::string("OpenCV exception caught: ").append(e.what()).c_str());
   } catch(...) {
     mexErrMsgTxt("Uncaught exception occurred in {{fun.name}}");
   }
diff --git a/modules/matlab/test/test_compiler.cpp b/modules/matlab/test/test_compiler.cpp
new file mode 100644 (file)
index 0000000..78995e2
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * file:   rand.cpp
+ * author: A trusty code generator
+ * date:   Wed, 19 Jun 2013 11:15:15
+ * 
+ * This file was autogenerated, do not modify.
+ * See LICENCE for full modification and redistribution details.
+ * Copyright 2013 The OpenCV Foundation
+ */
+#include "mex.h"
+#include "bridge.hpp"
+#include <vector>
+
+/* 
+ * rand
+ * Gateway routine
+ *   nlhs - number of return arguments
+ *   plhs - pointers to return arguments
+ *   nrhs - number of input arguments
+ *   prhs - pointers to input arguments
+ */
+void mexFunction(int nlhs, mxArray* plhs[],
+                 int nrhs, const mxArray* prhs[]) {
+
+  // call the opencv function
+  // [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn);
+  try {
+    rand();
+  } catch(...) {
+    mexErrMsgTxt("Uncaught exception occurred in rand");
+  }
+}
similarity index 69%
rename from modules/matlab/test/rand.hpp
rename to modules/matlab/test/test_generator.hpp
index 78e3118..c633b2f 100644 (file)
@@ -3,8 +3,8 @@
  * part of <cstdlib>, so we can be reasonably sure its
  * definition will be found
  */
-#ifndef __OPENCV_MATLAB_TEST_COMPILER_HPP_
-#define __OPENCV_MATLAB_TEST_COMPILER_HPP_
+#ifndef __OPENCV_MATLAB_TEST_GENERATOR_HPP_
+#define __OPENCV_MATLAB_TEST_GENERATOR_HPP_
 
 namespace cv {