matlabinterface.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //
  2. // IGL Lib - Simple C++ mesh library
  3. //
  4. // Copyright 2011, Daniele Panozzo. All rights reserved.
  5. // WARNING: These functions require matlab installed
  6. // Additional header folder required:
  7. // /Applications/MATLAB_R2011a.app/extern/include
  8. // Additional binary lib to be linked with:
  9. // /Applications/MATLAB_R2011a.app/bin/maci64/libeng.dylib
  10. // /Applications/MATLAB_R2011a.app/bin/maci64/libmx.dylib
  11. // MAC ONLY:
  12. // Add to the environment variables:
  13. // DYLD_LIBRARY_PATH = /Applications/MATLAB_R2011a.app/bin/maci64
  14. // PATH = /opt/local/bin:/opt/local/sbin:/Applications/MATLAB_R2011a.app/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
  15. #ifndef MATLAB_INTERFACE_H
  16. #define MATLAB_INTERFACE_H
  17. #include <Eigen/Core>
  18. #include <string>
  19. #include <complex>
  20. #include <cassert>
  21. #include <map>
  22. #include <string>
  23. #include <vector>
  24. #include "engine.h" // Matlab engine header
  25. namespace igl
  26. {
  27. // Init the MATLAB engine
  28. // (no need to call it directly since it is automatically invoked by any other command)
  29. inline void mlinit(Engine** engine);
  30. // Closes the MATLAB engine
  31. inline void mlclose(Engine** engine);
  32. // Send a matrix to MATLAB
  33. inline void mlsetmatrix(Engine** engine, std::string name, const Eigen::MatrixXd& M);
  34. // Send a matrix to MATLAB
  35. inline void mlsetmatrix(Engine** engine, std::string name, const Eigen::MatrixXi& M);
  36. // Receive a matrix from MATLAB
  37. inline void mlgetmatrix(Engine** engine, std::string name, Eigen::MatrixXd& M);
  38. // Receive a matrix from MATLAB
  39. inline void mlgetmatrix(Engine** engine, std::string name, Eigen::MatrixXi& M);
  40. // Send a single scalar to MATLAB
  41. inline void mlsetscalar(Engine** engine, std::string name, double s);
  42. // Receive a single scalar from MATLAB
  43. inline double mlgetscalar(Engine** engine, std::string name);
  44. // Execute arbitrary MATLAB code and return the MATLAB output
  45. inline std::string mleval(Engine** engine, std::string code);
  46. }
  47. //Implementation
  48. // Init the MATLAB engine
  49. // (no need to call it directly since it is automatically invoked by any other command)
  50. inline void igl::mlinit(Engine** mlengine)
  51. {
  52. *mlengine = engOpen("\0");
  53. }
  54. // Closes the MATLAB engine
  55. inline void igl::mlclose(Engine** mlengine)
  56. {
  57. engClose(*mlengine);
  58. *mlengine = 0;
  59. }
  60. // Send a matrix to MATLAB
  61. inline void igl::mlsetmatrix(Engine** mlengine, std::string name, const Eigen::MatrixXd& M)
  62. {
  63. if (*mlengine == 0)
  64. mlinit(mlengine);
  65. mxArray *A = mxCreateDoubleMatrix(M.rows(), M.cols(), mxREAL);
  66. double *pM = mxGetPr(A);
  67. int c = 0;
  68. for(int j=0; j<M.cols();++j)
  69. for(int i=0; i<M.rows();++i)
  70. pM[c++] = double(M(i,j));
  71. engPutVariable(*mlengine, name.c_str(), A);
  72. mxDestroyArray(A);
  73. }
  74. // Send a matrix to MATLAB
  75. inline void igl::mlsetmatrix(Engine** mlengine, std::string name, const Eigen::MatrixXi& M)
  76. {
  77. if (*mlengine == 0)
  78. mlinit(mlengine);
  79. mxArray *A = mxCreateDoubleMatrix(M.rows(), M.cols(), mxREAL);
  80. double *pM = mxGetPr(A);
  81. int c = 0;
  82. for(int j=0; j<M.cols();++j)
  83. for(int i=0; i<M.rows();++i)
  84. pM[c++] = double(M(i,j))+1;
  85. engPutVariable(*mlengine, name.c_str(), A);
  86. mxDestroyArray(A);
  87. }
  88. // Receive a matrix from MATLAB
  89. inline void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::MatrixXd& M)
  90. {
  91. if (*mlengine == 0)
  92. mlinit(mlengine);
  93. unsigned long m = 0;
  94. unsigned long n = 0;
  95. std::vector<double> t;
  96. mxArray *ary = engGetVariable(*mlengine, name.c_str());
  97. if (ary == NULL)
  98. {
  99. m = 0;
  100. n = 0;
  101. M = Eigen::MatrixXd(0,0);
  102. }
  103. else
  104. {
  105. m = mxGetM(ary);
  106. n = mxGetN(ary);
  107. M = Eigen::MatrixXd(m,n);
  108. double *pM = mxGetPr(ary);
  109. int c = 0;
  110. for(int j=0; j<M.cols();++j)
  111. for(int i=0; i<M.rows();++i)
  112. M(i,j) = pM[c++];
  113. }
  114. mxDestroyArray(ary);
  115. }
  116. // Receive a matrix from MATLAB
  117. inline void igl::mlgetmatrix(Engine** mlengine, std::string name, Eigen::MatrixXi& M)
  118. {
  119. if (*mlengine == 0)
  120. mlinit(mlengine);
  121. unsigned long m = 0;
  122. unsigned long n = 0;
  123. std::vector<double> t;
  124. mxArray *ary = engGetVariable(*mlengine, name.c_str());
  125. if (ary == NULL)
  126. {
  127. m = 0;
  128. n = 0;
  129. M = Eigen::MatrixXi(0,0);
  130. }
  131. else
  132. {
  133. m = mxGetM(ary);
  134. n = mxGetN(ary);
  135. M = Eigen::MatrixXi(m,n);
  136. double *pM = mxGetPr(ary);
  137. int c = 0;
  138. for(int j=0; j<M.cols();++j)
  139. for(int i=0; i<M.rows();++i)
  140. M(i,j) = int(pM[c++])-1;
  141. }
  142. mxDestroyArray(ary);
  143. }
  144. // Send a single scalar to MATLAB
  145. inline void igl::mlsetscalar(Engine** mlengine, std::string name, double s)
  146. {
  147. if (*mlengine == 0)
  148. mlinit(mlengine);
  149. Eigen::MatrixXd M(1,1);
  150. M(0,0) = s;
  151. mlsetmatrix(mlengine, name, M);
  152. }
  153. // Receive a single scalar from MATLAB
  154. inline double igl::mlgetscalar(Engine** mlengine, std::string name)
  155. {
  156. if (*mlengine == 0)
  157. mlinit(mlengine);
  158. Eigen::MatrixXd M;
  159. mlgetmatrix(mlengine, name,M);
  160. return M(0,0);
  161. }
  162. // Execute arbitrary MATLAB code and return the MATLAB output
  163. inline std::string igl::mleval(Engine** mlengine, std::string code)
  164. {
  165. if (*mlengine == 0)
  166. mlinit(mlengine);
  167. const char *matlab_code = code.c_str();
  168. const int BUF_SIZE = 4096*4096;
  169. // allocate on the heap to avoid running out of stack
  170. std::string bufauto(BUF_SIZE+1, '\0');
  171. char *buf = &bufauto[0];
  172. assert(matlab_code != NULL);
  173. // Use RAII ensure that on leaving this scope, the output buffer is
  174. // always nullified (to prevent Matlab from accessing memory that might
  175. // have already been deallocated).
  176. struct cleanup {
  177. Engine *m_ep;
  178. cleanup(Engine *ep) : m_ep(ep) { }
  179. ~cleanup() { engOutputBuffer(m_ep, NULL, 0); }
  180. } cleanup_obj(*mlengine);
  181. if (buf != NULL)
  182. engOutputBuffer(*mlengine, buf, BUF_SIZE);
  183. int res = engEvalString(*mlengine, matlab_code);
  184. if (res != 0) {
  185. std::ostringstream oss;
  186. oss << "ERROR: Matlab command failed with error code " << res << ".\n";
  187. return oss.str();
  188. }
  189. if (buf[0] == '>' && buf[1] == '>' && buf[2] == ' ')
  190. buf += 3;
  191. if (buf[0] == '\n') ++buf;
  192. return std::string(buf);
  193. }
  194. #endif