GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-java.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2007, 2013 Michael Goffioul
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include "defun.h"
28 #include "error.h"
29 #include "fpucw.h"
30 
31 #if HAVE_FPU_CONTROL_H
32 #include <fpu_control.h>
33 #endif
34 
35 #if defined HAVE_JAVA
36 
37 #if defined (HAVE_WINDOWS_H)
38 #include <windows.h>
39 #endif
40 
41 #include <algorithm>
42 #include <map>
43 #include <iostream>
44 #include <fstream>
45 #include <string>
46 
47 #include <clocale>
48 
49 #include "Cell.h"
50 #include "cmd-edit.h"
51 #include "defaults.h"
52 #include "file-ops.h"
53 #include "file-stat.h"
54 #include "load-path.h"
55 #include "oct-env.h"
56 #include "oct-shlib.h"
57 #include "ov-java.h"
58 #include "parse.h"
59 #include "variables.h"
60 
61 typedef jint (JNICALL *JNI_CreateJavaVM_t) (JavaVM **pvm, JNIEnv **penv,
62  void *args);
63 typedef jint (JNICALL *JNI_GetCreatedJavaVMs_t) (JavaVM **pvm, jsize bufLen,
64  jsize *nVMs);
65 
66 extern "C"
67 {
68  JNIEXPORT jboolean JNICALL
69  Java_org_octave_Octave_call (JNIEnv *, jclass, jstring, jobjectArray,
70  jobjectArray);
71  JNIEXPORT void JNICALL
72  Java_org_octave_OctaveReference_doFinalize (JNIEnv *, jclass, jint);
73 
74  JNIEXPORT void JNICALL
75  Java_org_octave_Octave_doInvoke (JNIEnv *, jclass, jint, jobjectArray);
76 
77  JNIEXPORT void JNICALL
78  Java_org_octave_Octave_doEvalString (JNIEnv *, jclass, jstring);
79 
80  JNIEXPORT jboolean JNICALL
81  Java_org_octave_Octave_needThreadedInvokation (JNIEnv *, jclass);
82 }
83 
84 static JavaVM *jvm = 0;
85 static bool jvm_attached = false;
86 
87 // Need to keep hold of the shared library handle until exit.
88 static octave_shlib jvm_lib;
89 
90 static std::map<int,octave_value> listener_map;
91 static std::map<int,octave_value> octave_ref_map;
92 static int octave_java_refcount = 0;
93 static long octave_thread_ID = -1;
94 
95 bool Vjava_matrix_autoconversion = false;
97 bool Vdebug_java = false;
98 
99 class JVMArgs
100 {
101 public:
102 
103  JVMArgs (void)
104  {
105  vm_args.version = JNI_VERSION_1_2;
106  vm_args.nOptions = 0;
107  vm_args.options = 0;
108  vm_args.ignoreUnrecognized = false;
109  }
110 
111  ~JVMArgs (void)
112  {
113  clean ();
114  }
115 
116  JavaVMInitArgs* to_args ()
117  {
118  update ();
119  return &vm_args;
120  }
121 
122  void add (const std::string& opt)
123  {
124  java_opts.push_back (opt);
125  }
126 
127  void read_java_opts (const std::string& filename)
128  {
129  std::ifstream js (filename.c_str ());
130 
131  if (! js.bad () && ! js.fail ())
132  {
133  std::string line;
134 
135  while (! js.eof () && ! js.fail ())
136  {
137  std::getline (js, line);
138  if (line.length () > 2
139  && (line.find ("-D") == 0 || line.find ("-X") == 0))
140  java_opts.push_back (line);
141  else if (line.length () > 0 && Vdebug_java)
142  std::cerr << "invalid JVM option, skipping: " << line << std::endl;
143  }
144  }
145  }
146 
147 private:
148 
149  void clean (void)
150  {
151  if (vm_args.options != 0)
152  {
153  for (int i = 0; i < vm_args.nOptions; i++)
154  delete [] vm_args.options[i].optionString;
155  delete [] vm_args.options;
156 
157  vm_args.options = 0;
158  vm_args.nOptions = 0;
159  }
160  }
161 
162  void update (void)
163  {
164  clean ();
165 
166  if (java_opts.size () > 0)
167  {
168  int index = 0;
169 
170  vm_args.nOptions = java_opts.size ();
171  vm_args.options = new JavaVMOption [vm_args.nOptions];
172  for (std::list<std::string>::const_iterator it = java_opts.begin ();
173  it != java_opts.end (); ++it)
174  {
175  if (Vdebug_java)
176  std::cout << *it << std::endl;
177  vm_args.options[index++].optionString = strsave ((*it).c_str ());
178  }
179  java_opts.clear ();
180  }
181  }
182 
183 private:
184 
185  JavaVMInitArgs vm_args;
186 
187  std::list<std::string> java_opts;
188 };
189 
190 #ifdef __WIN32__
191 static std::string
192 read_registry_string (const std::string& key, const std::string& value)
193 {
194  HKEY hkey;
195  DWORD len;
196 
197  std::string retval;
198 
199  if (! RegOpenKeyEx (HKEY_LOCAL_MACHINE, key.c_str (), 0, KEY_READ, &hkey))
200  {
201  if (! RegQueryValueEx (hkey, value.c_str (), 0, 0, 0, &len))
202  {
203  retval.resize (len);
204  if (RegQueryValueEx (hkey, value.c_str (), 0, 0,
205  (LPBYTE)&retval[0], &len))
206  retval = "";
207  else if (retval[len-1] == '\0')
208  retval.resize (--len);
209  }
210  RegCloseKey (hkey);
211  }
212 
213  return retval;
214 }
215 
216 static std::string
217 get_module_filename (HMODULE hMod)
218 {
219  int n = 1024;
220  std::string retval (n, '\0');
221  bool found = false;
222 
223  while (n < 65536)
224  {
225  int status = GetModuleFileName(hMod, &retval[0], n);
226 
227  if (status < n)
228  {
229  retval.resize (n);
230  found = true;
231  break;
232  }
233  else
234  {
235  n *= 2;
236  retval.resize (n);
237  }
238  }
239  return (found ? retval : "");
240 }
241 
242 static void
243 set_dll_directory (const std::string& dir = "")
244 {
245  typedef BOOL (WINAPI *dllfcn_t) (LPCTSTR path);
246 
247  static dllfcn_t dllfcn = 0;
248  static bool first = true;
249 
250  if (! dllfcn && first)
251  {
252  HINSTANCE hKernel32 = GetModuleHandle ("kernel32");
253  dllfcn = reinterpret_cast<dllfcn_t> (GetProcAddress (hKernel32,
254  "SetDllDirectoryA"));
255  first = false;
256  }
257 
258  if (dllfcn)
259  dllfcn (dir.empty () ? 0 : dir.c_str ());
260 }
261 #endif
262 
263 static std::string
264 initial_java_dir (void)
265 {
266  static std::string java_dir;
267 
268  if (java_dir.empty ())
269  {
270  java_dir = octave_env::getenv ("OCTAVE_JAVA_DIR");
271 
272  if (java_dir.empty ())
273  java_dir = Vfcn_file_dir + file_ops::dir_sep_str () + "java";
274  }
275 
276  return java_dir;
277 }
278 
279 // Read the content of a file filename (usually "classpath.txt")
280 //
281 // Returns a string with all lines concatenated and separated
282 // by the path separator character.
283 // The return string also starts with a path separator so that
284 // it can be appended easily to a base classpath.
285 //
286 // The file "classpath.txt" must contain single lines, each
287 // with a classpath.
288 // Comment lines starting with a '#' or a '%' in column 1 are allowed.
289 
290 static std::string
291 read_classpath_txt (const std::string& filepath)
292 {
293  std::string classpath;
294 
295  std::ifstream fs (filepath.c_str ());
296 
297  if (! fs.bad () && ! fs.fail ())
298  {
299  std::string line;
300 
301  while (! fs.eof () && ! fs.fail ())
302  {
303  std::getline (fs, line);
304 
305  if (line.length () > 0)
306  {
307  if (line[0] == '#' || line[0] == '%')
308  ; // skip comments
309  else
310  {
311  // prepend separator character
312  classpath.append (dir_path::path_sep_str ());
313 
314  // append content of line without whitespace
315  int last = line.find_last_not_of (" \t\f\v\r\n");
316 
317  classpath.append (file_ops::tilde_expand (line.substr (0, last+1)));
318  }
319  }
320  }
321  }
322 
323  return (classpath);
324 }
325 
326 static std::string
327 initial_class_path (void)
328 {
329  std::string java_dir = initial_java_dir ();
330 
331  std::string retval = java_dir;
332 
333  // find octave.jar file
334  if (! retval.empty ())
335  {
336  std::string sep = file_ops::dir_sep_str ();
337 
338  std::string jar_file = java_dir + sep + "octave.jar";
339 
340  file_stat jar_exists (jar_file);
341 
342  if (jar_exists)
343  {
344  // initialize static classpath to octave.jar
345  retval = jar_file;
346 
347  // The base classpath has been set.
348  // Try to find an optional file specifying classpaths in 3 places.
349  // 1) Current directory
350  // 2) User's home directory
351  // 3) Octave installation directory where octave.jar resides
352 
353  // The filename is "javaclasspath.txt", but historically
354  // has been "classpath.txt" so both are supported.
355  std::string cp_list[] = {"javaclasspath.txt", "classpath.txt"};
356 
357  for (int i=0; i<2; i++)
358  {
359  std::string filename = cp_list[i];
360  std::string cp_file = filename;
361  file_stat cp_exists;
362 
363  // Try to find classpath file in the current directory.
364 
365  cp_exists = file_stat (cp_file);
366  if (cp_exists)
367  {
368  // File found. Add its contents to the static classpath.
369  std::string classpath = read_classpath_txt (cp_file);
370  retval.append (classpath);
371  }
372 
373  // Try to find classpath file in the user's home directory.
374 
375  cp_file = "~" + sep + filename;
376  cp_file = file_ops::tilde_expand (cp_file);
377  cp_exists = file_stat (cp_file);
378  if (cp_exists)
379  {
380  // File found. Add its contents to the static classpath.
381  std::string classpath = read_classpath_txt (cp_file);
382  retval.append (classpath);
383  }
384 
385  // Try to find classpath file in the Octave install directory.
386 
387  cp_file = java_dir + sep + filename;
388  cp_exists = file_stat (cp_file);
389  if (cp_exists)
390  {
391  // File found. Add its contents to the static classpath.
392  std::string classpath = read_classpath_txt (cp_file);
393  retval.append (classpath);
394  }
395  }
396  }
397  else
398  throw std::string ("octave.jar does not exist: ") + jar_file;
399  }
400  else
401  throw std::string ("initial java dir is empty");
402 
403  return retval;
404 }
405 
406 #ifndef _FPU_DEFAULT
407 #if defined __i386__ || defined __x86_64__
408 #define _FPU_DEFAULT 0x037f
409 #else
410 #define _FPU_DEFAULT 0
411 #endif
412 #endif
413 
414 static void
415 restore_fpu_state (void)
416 {
417  fpucw_t cw = GET_FPUCW ();
418  if (cw != _FPU_DEFAULT)
419  SET_FPUCW (_FPU_DEFAULT);
420 }
421 
422 static void
423 initialize_jvm (void)
424 {
425  // Most of the time JVM already exists and has been initialized.
426  if (jvm)
427  return;
428 
429  JNIEnv *current_env;
430  const char *static_locale = setlocale (LC_ALL, 0);
431  const std::string locale (static_locale);
432 
433 #if defined (__WIN32__)
434 
435  HMODULE hMod = GetModuleHandle ("jvm.dll");
436  std::string jvm_lib_path;
437  std::string old_cwd;
438 
439  if (hMod)
440  {
441  // JVM seems to be already loaded, better to use that DLL instead
442  // of looking in the registry, to avoid opening a different JVM.
443  jvm_lib_path = get_module_filename (hMod);
444 
445  if (jvm_lib_path.empty ())
446  throw std::string ("unable to find Java Runtime Environment");
447  }
448  else
449  {
450  // In windows, find the location of the JRE from the registry
451  // and load the symbol from the dll.
452  std::string key, value;
453 
454  key = "software\\javasoft\\java runtime environment";
455 
456  value = octave_env::getenv ("JAVA_VERSION");
457  if (value.empty ())
458  {
459  value = "Currentversion";
460  std::string regval = read_registry_string (key,value);
461 
462  if (regval.empty ())
463  throw std::string ("unable to find Java Runtime Environment: ")
464  + key + "::" + value;
465  value = regval;
466  }
467 
468  key = key + "\\" + value;
469  value = "RuntimeLib";
470  jvm_lib_path = read_registry_string (key, value);
471  if (jvm_lib_path.empty ())
472  throw std::string ("unable to find Java Runtime Environment: ")
473  + key + "::" + value;
474 
475  std::string jvm_bin_path;
476 
477  value = "JavaHome";
478  jvm_bin_path = read_registry_string (key, value);
479  if (! jvm_bin_path.empty ())
480  {
481  jvm_bin_path = (jvm_bin_path + std::string ("\\bin"));
482 
484 
485  set_dll_directory (jvm_bin_path);
486  octave_env::chdir (jvm_bin_path);
487  }
488  }
489 
490 #else // Not Win32 system
491 
492  // JAVA_LDPATH determined by configure and set in config.h
493 #if defined (__APPLE__)
494  std::string jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.dylib");
495 #else
496  std::string jvm_lib_path = JAVA_LDPATH + std::string ("/libjvm.so");
497 #endif
498 
499 #endif
500 
501  jsize nVMs = 0;
502 
503 # if !defined (__APPLE__) && !defined (__MACH__)
504 
505  octave_shlib lib (jvm_lib_path);
506 
507  if (!lib)
508  throw std::string ("unable to load Java Runtime Environment from ")
509  + jvm_lib_path;
510 
511 #if defined (__WIN32__)
512 
513  set_dll_directory ();
514 
515  if (! old_cwd.empty ())
516  octave_env::chdir (old_cwd);
517 
518 #endif
519 
520  JNI_CreateJavaVM_t create_vm =
521  reinterpret_cast<JNI_CreateJavaVM_t> (lib.search ("JNI_CreateJavaVM"));
522  JNI_GetCreatedJavaVMs_t get_vm =
523  reinterpret_cast<JNI_GetCreatedJavaVMs_t> (lib.search ("JNI_GetCreatedJavaVMs"));
524 
525  if (!create_vm)
526  throw std::string ("unable to find JNI_CreateJavaVM in ") + jvm_lib_path;
527 
528  if (!get_vm)
529  throw std::string ("unable to find JNI_GetCreatedJavaVMs in ")
530  + jvm_lib_path;
531 
532  if (get_vm (&jvm, 1, &nVMs) == 0 && nVMs > 0)
533 
534 #else
535 
536  // FIXME: There exists a problem on the Mac platform that
537  // octave_shlib lib (jvm_lib_path)
538  // doesn't work with 'not-bundled' *.oct files.
539 
540  if (JNI_GetCreatedJavaVMs (&jvm, 1, &nVMs) == 0 && nVMs > 0)
541 
542 #endif
543 
544  {
545  // At least one JVM exists, try to attach to it
546 
547  switch (jvm->GetEnv (reinterpret_cast<void **> (&current_env),
548  JNI_VERSION_1_2))
549  {
550  case JNI_EDETACHED:
551  // Attach the current thread
552  JavaVMAttachArgs vm_args;
553  vm_args.version = JNI_VERSION_1_2;
554  vm_args.name = const_cast<char *> ("octave");
555  vm_args.group = 0;
556  if (jvm->AttachCurrentThread (reinterpret_cast<void **> (&current_env),
557  &vm_args) < 0)
558  throw std::string ("JVM internal error, unable to attach octave to existing JVM");
559  break;
560 
561  case JNI_EVERSION:
562  throw std::string ("JVM internal error, the required JNI version is not supported");
563  break;
564 
565  case JNI_OK:
566  // Don't do anything, the current thread is already attached to JVM
567  break;
568  }
569 
570  jvm_attached = true;
571  //printf ("JVM attached\n");
572  }
573  else
574  {
575  // No JVM exists, create one
576 
577  JVMArgs vm_args;
578 
579  vm_args.add ("-Djava.class.path=" + initial_class_path ());
580  vm_args.add ("-Xrs");
581  vm_args.add ("-Djava.system.class.loader=org.octave.OctClassLoader");
582  vm_args.read_java_opts (initial_java_dir () + file_ops::dir_sep_str () +
583  "java.opts");
584 
585 # if !defined (__APPLE__) && !defined (__MACH__)
586 
587  if (create_vm (&jvm, &current_env, vm_args.to_args ()) != JNI_OK)
588  throw std::string ("unable to start Java VM in ")+jvm_lib_path;
589  //printf ("JVM created\n");
590  }
591 
592  jvm_lib = lib;
593 
594 #else
595 
596  if (JNI_CreateJavaVM (&jvm, reinterpret_cast<void **> (&current_env),
597  vm_args.to_args ()) != JNI_OK)
598  throw std::string ("unable to start Java VM in ")+jvm_lib_path;
599 
600  }
601 
602 #endif
603 
604  setlocale (LC_ALL, locale.c_str ());
605 }
606 
607 static void
608 terminate_jvm (void)
609 {
610  if (jvm)
611  {
612  if (jvm_attached)
613  jvm->DetachCurrentThread ();
614  else
615  jvm->DestroyJavaVM ();
616 
617  jvm = 0;
618  jvm_attached = false;
619 
620  if (jvm_lib)
621  jvm_lib.close ();
622 
623  restore_fpu_state ();
624  }
625 }
626 
627 std::string
628 jstring_to_string (JNIEnv* jni_env, jstring s)
629 {
630  std::string retval;
631 
632  if (jni_env)
633  {
634  const char *cstr = jni_env->GetStringUTFChars (s, 0);
635  retval = cstr;
636  jni_env->ReleaseStringUTFChars (s, cstr);
637  }
638 
639  return retval;
640 }
641 
642 std::string
643 jstring_to_string (JNIEnv* jni_env, jobject obj)
644 {
645  std::string retval;
646 
647  if (jni_env && obj)
648  {
649  jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/String"));
650  if (cls)
651  {
652  if (jni_env->IsInstanceOf (obj, cls))
653  retval = jstring_to_string (jni_env,
654  reinterpret_cast<jstring> (obj));
655  }
656  }
657 
658  return retval;
659 }
660 
661 bool
662 octave_java::is_java_string (void) const
663 {
664  JNIEnv *current_env = thread_jni_env ();
665 
666  if (current_env && java_object)
667  {
668  jclass_ref cls (current_env, current_env->FindClass ("java/lang/String"));
669  return current_env->IsInstanceOf (java_object, cls);
670  }
671 
672  return false;
673 }
674 
675 bool
676 octave_java::is_instance_of (const std::string& cls_name) const
677 {
678  JNIEnv *current_env = thread_jni_env ();
679 
680  std::string cls_cpp = cls_name;
681  std::replace (cls_cpp.begin (), cls_cpp.end (), '.', '/');
682 
683  if (current_env && java_object)
684  {
685  jclass_ref cls (current_env, current_env->FindClass (cls_cpp.c_str ()));
686  if (current_env->ExceptionCheck ())
687  current_env->ExceptionClear();
688  else
689  return current_env->IsInstanceOf (java_object, cls);
690  }
691  return false;
692 }
693 
694 static octave_value
695 check_exception (JNIEnv* jni_env)
696 {
697  octave_value retval;
698 
699  jthrowable_ref ex (jni_env, jni_env->ExceptionOccurred ());
700 
701  if (ex)
702  {
703  if (Vdebug_java)
704  jni_env->ExceptionDescribe ();
705 
706  jni_env->ExceptionClear ();
707 
708  jclass_ref jcls (jni_env, jni_env->GetObjectClass (ex));
709  jmethodID mID = jni_env->GetMethodID (jcls, "toString",
710  "()Ljava/lang/String;");
711  jstring_ref js (jni_env,
712  reinterpret_cast<jstring> (jni_env->CallObjectMethod (ex, mID)));
713  std::string msg = jstring_to_string (jni_env, js);
714 
715  error ("[java] %s", msg.c_str ());
716  }
717  else
718  retval = Matrix ();
719 
720  return retval;
721 }
722 
723 static jclass
724 find_octave_class (JNIEnv *jni_env, const char *name)
725 {
726  static std::string class_loader;
727  static jclass uiClass = 0;
728 
729  jclass jcls = jni_env->FindClass (name);
730 
731  if (jcls == 0)
732  {
733  jni_env->ExceptionClear ();
734 
735  if (! uiClass)
736  {
737  if (class_loader.empty ())
738  {
739  jclass_ref syscls (jni_env,
740  jni_env->FindClass ("java/lang/System"));
741  jmethodID mID = jni_env->GetStaticMethodID (syscls, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
742  jstring_ref js (jni_env, jni_env->NewStringUTF ("octave.class.loader"));
743  js = reinterpret_cast<jstring> (jni_env->CallStaticObjectMethod (syscls, mID, jstring (js)));
744  class_loader = jstring_to_string (jni_env, jstring (js));
745  std::replace (class_loader.begin (), class_loader.end (),
746  '.', '/');
747  }
748 
749  jclass_ref uicls (jni_env, jni_env->FindClass (class_loader.c_str ()));
750 
751  if (! uicls)
752  {
753  jni_env->ExceptionClear ();
754 
755  /* Try the netbeans way */
756  std::replace (class_loader.begin (), class_loader.end (),
757  '/', '.');
758  jclass_ref jcls2 (jni_env, jni_env->FindClass ("org/openide/util/Lookup"));
759  jmethodID mID = jni_env->GetStaticMethodID (jcls2, "getDefault", "()Lorg/openide/util/Lookup;");
760  jobject_ref lObj (jni_env, jni_env->CallStaticObjectMethod (jcls2, mID));
761  mID = jni_env->GetMethodID (jcls2, "lookup",
762  "(Ljava/lang/Class;)Ljava/lang/Object;");
763  jclass_ref cLoaderCls (jni_env, jni_env->FindClass ("java/lang/ClassLoader"));
764  jobject_ref cLoader (jni_env, jni_env->CallObjectMethod (lObj, mID, jclass (cLoaderCls)));
765  mID = jni_env->GetMethodID (cLoaderCls, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
766  jstring_ref js (jni_env, jni_env->NewStringUTF (class_loader.c_str ()));
767  uicls = reinterpret_cast<jclass> (jni_env->CallObjectMethod (cLoader, mID, jstring (js)));
768  }
769 
770  if (uicls)
771  uiClass = reinterpret_cast<jclass> (jni_env->NewGlobalRef (jclass (uicls)));
772  }
773 
774  if (uiClass)
775  {
776  jmethodID mID = jni_env->GetStaticMethodID (uiClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
777  jstring_ref js (jni_env, jni_env->NewStringUTF (name));
778  jcls = reinterpret_cast<jclass> (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js)));
779  }
780  }
781 
782  return jcls;
783 }
784 
785 static dim_vector
786 compute_array_dimensions (JNIEnv* jni_env, jobject obj)
787 {
788  jobjectArray_ref jobj (jni_env, reinterpret_cast<jobjectArray> (obj));
789  jclass_ref jcls (jni_env, jni_env->GetObjectClass (obj));
790  jclass_ref ccls (jni_env, jni_env->GetObjectClass (jcls));
791  jmethodID isArray_ID = jni_env->GetMethodID (ccls, "isArray", "()Z");
792  jmethodID getComponentType_ID = jni_env->GetMethodID (ccls, "getComponentType", "()Ljava/lang/Class;");
793 
794  dim_vector dv (1, 1);
795  int idx = 0;
796 
797  jobj.detach ();
798  while (jcls && jni_env->CallBooleanMethod (jcls, isArray_ID))
799  {
800  int len = (jobj ? jni_env->GetArrayLength (jobj) : 0);
801  if (idx >= dv.length ())
802  dv.resize (idx+1);
803  dv(idx) = len;
804  jcls = reinterpret_cast<jclass> (jni_env->CallObjectMethod (jcls, getComponentType_ID));
805  jobj = (len > 0 ? reinterpret_cast<jobjectArray> (jni_env->GetObjectArrayElement (jobj, 0)) : 0);
806  idx++;
807  }
808 
809  restore_fpu_state ();
810 
811  return dv;
812 }
813 
814 static jobject
815 make_java_index (JNIEnv* jni_env, const octave_value_list& idx)
816 {
817  jclass_ref ocls (jni_env, jni_env->FindClass ("[I"));
818  jobjectArray retval = jni_env->NewObjectArray (idx.length (), ocls, 0);
819 
820  for (int i = 0; i < idx.length (); i++)
821  {
822  idx_vector v = idx(i).index_vector ();
823 
824  if (! error_state)
825  {
826  jintArray_ref i_array (jni_env, jni_env->NewIntArray (v.length ()));
827  jint *buf = jni_env->GetIntArrayElements (i_array, 0);
828 
829  for (int k = 0; k < v.length (); k++)
830  buf[k] = v(k);
831 
832  jni_env->ReleaseIntArrayElements (i_array, buf, 0);
833  jni_env->SetObjectArrayElement (retval, i, i_array);
834 
835  check_exception (jni_env);
836 
837  if (error_state)
838  break;
839  }
840  else
841  break;
842  }
843 
844  return retval;
845 }
846 
847 static octave_value
848 get_array_elements (JNIEnv* jni_env, jobject jobj,
849  const octave_value_list& idx)
850 {
851  octave_value retval;
852  jobject_ref resObj (jni_env);
853  jobject_ref java_idx (jni_env, make_java_index (jni_env, idx));
854 
855  if (! error_state)
856  {
857  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
858  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsref", "(Ljava/lang/Object;[[I)Ljava/lang/Object;");
859  resObj = jni_env->CallStaticObjectMethod (helperClass, mID, jobj, jobject (java_idx));
860  }
861 
862  if (resObj)
863  retval = box (jni_env, resObj);
864  else
865  retval = check_exception (jni_env);
866 
867  restore_fpu_state ();
868 
869  return retval;
870 }
871 
872 static octave_value
873 set_array_elements (JNIEnv* jni_env, jobject jobj,
874  const octave_value_list& idx, const octave_value& rhs)
875 {
876  octave_value retval;
877 
878  jclass_ref rhsCls (jni_env);
879  jobject_ref resObj (jni_env);
880  jobject_ref rhsObj (jni_env);
881  jobject_ref java_idx (jni_env, make_java_index (jni_env, idx));
882 
883  if (! error_state && unbox (jni_env, rhs, rhsObj, rhsCls))
884  {
885  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
886  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsasgn",
887  "(Ljava/lang/Object;[[ILjava/lang/Object;)Ljava/lang/Object;");
888  resObj = jni_env->CallStaticObjectMethod (helperClass, mID,
889  jobj, jobject (java_idx), jobject (rhsObj));
890  }
891 
892  if (resObj)
893  retval = box (jni_env, resObj);
894  else
895  retval = check_exception (jni_env);
896 
897  restore_fpu_state ();
898 
899  return retval;
900 }
901 
902 static string_vector
903 get_invoke_list (JNIEnv* jni_env, jobject jobj)
904 {
905  std::list<std::string> name_list;
906 
907  if (jni_env)
908  {
909  jclass_ref cls (jni_env, jni_env->GetObjectClass (jobj));
910  jclass_ref ccls (jni_env, jni_env->GetObjectClass (cls));
911  jmethodID getMethods_ID = jni_env->GetMethodID (ccls, "getMethods", "()[Ljava/lang/reflect/Method;");
912  jmethodID getFields_ID = jni_env->GetMethodID (ccls, "getFields", "()[Ljava/lang/reflect/Field;");
913  jobjectArray_ref mList (jni_env, reinterpret_cast<jobjectArray> (jni_env->CallObjectMethod (cls, getMethods_ID)));
914  jobjectArray_ref fList (jni_env, reinterpret_cast<jobjectArray> (jni_env->CallObjectMethod (cls, getFields_ID)));
915  int mLen = jni_env->GetArrayLength (mList);
916  int fLen = jni_env->GetArrayLength (fList);
917  jclass_ref mCls (jni_env, jni_env->FindClass ("java/lang/reflect/Method"));
918  jclass_ref fCls (jni_env, jni_env->FindClass ("java/lang/reflect/Field"));
919  jmethodID m_getName_ID = jni_env->GetMethodID (mCls, "getName", "()Ljava/lang/String;");
920  jmethodID f_getName_ID = jni_env->GetMethodID (fCls, "getName", "()Ljava/lang/String;");
921 
922  for (int i = 0; i < mLen; i++)
923  {
924  jobject_ref meth (jni_env, jni_env->GetObjectArrayElement (mList, i));
925  jstring_ref methName (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (meth, m_getName_ID)));
926  name_list.push_back (jstring_to_string (jni_env, methName));
927  }
928 
929  for (int i = 0; i < fLen; i++)
930  {
931  jobject_ref field (jni_env, jni_env->GetObjectArrayElement (fList, i));
932  jstring_ref fieldName (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (field, f_getName_ID)));
933  name_list.push_back (jstring_to_string (jni_env, fieldName));
934  }
935 
936  restore_fpu_state ();
937  }
938 
939  string_vector v (name_list);
940 
941  return v.sort (true);
942 }
943 
944 static octave_value
945 convert_to_string (JNIEnv *jni_env, jobject java_object, bool force, char type)
946 {
947  octave_value retval;
948 
949  if (jni_env && java_object)
950  {
951  jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/String"));
952 
953  if (jni_env->IsInstanceOf (java_object, cls))
954  retval = octave_value (jstring_to_string (jni_env, java_object), type);
955  else if (force)
956  {
957  cls = jni_env->FindClass ("[Ljava/lang/String;");
958 
959  if (jni_env->IsInstanceOf (java_object, cls))
960  {
961  jobjectArray array = reinterpret_cast<jobjectArray> (java_object);
962  int len = jni_env->GetArrayLength (array);
963  Cell c (len, 1);
964 
965  for (int i = 0; i < len; i++)
966  {
967  jstring_ref js (jni_env, reinterpret_cast<jstring> (jni_env->GetObjectArrayElement (array, i)));
968 
969  if (js)
970  c(i) = octave_value (jstring_to_string (jni_env, js), type);
971  else
972  {
973  c(i) = check_exception (jni_env);
974 
975  if (error_state)
976  break;
977  }
978  }
979 
980  retval = octave_value (c);
981  }
982  else
983  {
984  cls = jni_env->FindClass ("java/lang/Object");
985  jmethodID mID = jni_env->GetMethodID (cls, "toString", "()Ljava/lang/String;");
986  jstring_ref js (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (java_object, mID)));
987 
988  if (js)
989  retval = octave_value (jstring_to_string (jni_env, js), type);
990  else
991  retval = check_exception (jni_env);
992  }
993  }
994  else
995  error ("unable to convert Java object to string");
996 
997  restore_fpu_state ();
998  }
999 
1000  return retval;
1001 }
1002 
1003 #define TO_JAVA(obj) dynamic_cast<octave_java*> ((obj).internal_rep ())
1004 
1006 box (JNIEnv* jni_env, jobject jobj, jclass jcls)
1007 {
1008  octave_value retval;
1009  jclass_ref cls (jni_env);
1010 
1011  if (! jobj)
1012  retval = Matrix ();
1013 
1014  while (retval.is_undefined ())
1015  {
1016  // Convert a scalar of any numeric class (byte, short, integer, long,
1017  // float, double) to a double value. Matlab does the same thing.
1018  cls = jni_env->FindClass ("java/lang/Number");
1019  if (jni_env->IsInstanceOf (jobj, cls))
1020  {
1021  jmethodID m = jni_env->GetMethodID (cls, "doubleValue", "()D");
1022  retval = jni_env->CallDoubleMethod (jobj, m);
1023  break;
1024  }
1025 
1026  cls = jni_env->FindClass ("java/lang/Boolean");
1027  if (jni_env->IsInstanceOf (jobj, cls))
1028  {
1029  jmethodID m = jni_env->GetMethodID (cls, "booleanValue", "()Z");
1030  retval = (jni_env->CallBooleanMethod (jobj, m) ? true : false);
1031  break;
1032  }
1033 
1034  cls = jni_env->FindClass ("java/lang/String");
1035  if (jni_env->IsInstanceOf (jobj, cls))
1036  {
1037  retval = jstring_to_string (jni_env, jobj);
1038  break;
1039  }
1040 
1041  cls = jni_env->FindClass ("java/lang/Character");
1042  if (jni_env->IsInstanceOf (jobj, cls))
1043  {
1044  jmethodID m = jni_env->GetMethodID (cls, "charValue", "()C");
1045  retval = jni_env->CallCharMethod (jobj, m);
1046  retval = retval.convert_to_str (false, true);
1047  break;
1048  }
1049 
1050 #define BOX_PRIMITIVE_ARRAY(JAVA_TYPE, JAVA_ID, JAVA_TYPE_CAP, OCTAVE_ID) \
1051  cls = jni_env->FindClass (JAVA_ID); \
1052  if (jni_env->IsInstanceOf (jobj, cls)) \
1053  { \
1054  const JAVA_TYPE ## Array jarr = reinterpret_cast<JAVA_TYPE ## Array> (jobj); \
1055  const jsize len = jni_env->GetArrayLength (jarr); \
1056  OCTAVE_ID ## NDArray d (dim_vector (len, 1)); \
1057  JAVA_TYPE * buffer = reinterpret_cast<JAVA_TYPE *> (d.fortran_vec ()); \
1058  jni_env->Get ## JAVA_TYPE_CAP ## ArrayRegion (jarr, 0, len, buffer); \
1059  retval = d; \
1060  break; \
1061  }
1062 
1063 BOX_PRIMITIVE_ARRAY (jboolean, "[Z", Boolean, bool)
1064 BOX_PRIMITIVE_ARRAY (jchar, "[C", Char, char)
1065 BOX_PRIMITIVE_ARRAY (jbyte, "[B", Byte, int8)
1066 BOX_PRIMITIVE_ARRAY (jshort, "[S", Short, int16)
1067 BOX_PRIMITIVE_ARRAY (jint, "[I", Int, int32)
1068 BOX_PRIMITIVE_ARRAY (jlong, "[J", Long, int64)
1069 BOX_PRIMITIVE_ARRAY (jfloat, "[F", Float, Float)
1070 BOX_PRIMITIVE_ARRAY (jdouble, "[D", Double, )
1071 
1072 #undef BOX_PRIMITIVE_ARRAY
1073 
1075  {
1076  cls = find_octave_class (jni_env, "org/octave/Matrix");
1077 
1078  if (jni_env->IsInstanceOf (jobj, cls))
1079  {
1080  jmethodID mID = jni_env->GetMethodID (cls, "getDims", "()[I");
1081  jintArray_ref iv (jni_env, reinterpret_cast<jintArray> (jni_env->CallObjectMethod (jobj, mID)));
1082  jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0);
1083  dim_vector dims;
1084  dims.resize (jni_env->GetArrayLength (jintArray (iv)));
1085 
1086  for (int i = 0; i < dims.length (); i++)
1087  dims(i) = iv_data[i];
1088 
1089  jni_env->ReleaseIntArrayElements (jintArray (iv), iv_data, 0);
1090  mID = jni_env->GetMethodID (cls, "getClassName", "()Ljava/lang/String;");
1091  jstring_ref js (jni_env, reinterpret_cast<jstring> (jni_env->CallObjectMethod (jobj, mID)));
1092 
1093  std::string s = jstring_to_string (jni_env, js);
1094 
1095  if (s == "double")
1096  {
1097  NDArray m (dims);
1098  mID = jni_env->GetMethodID (cls, "toDouble", "()[D");
1099  jdoubleArray_ref dv (jni_env, reinterpret_cast<jdoubleArray> (jni_env->CallObjectMethod (jobj, mID)));
1100  jni_env->GetDoubleArrayRegion (dv, 0, m.length (), m.fortran_vec ());
1101  retval = m;
1102  break;
1103  }
1104  else if (s == "byte")
1105  {
1107  {
1108  uint8NDArray m (dims);
1109  mID = jni_env->GetMethodID (cls, "toByte", "()[B");
1110  jbyteArray_ref dv (jni_env, reinterpret_cast<jbyteArray> (jni_env->CallObjectMethod (jobj, mID)));
1111  jni_env->GetByteArrayRegion (dv, 0, m.length (), reinterpret_cast<jbyte *> (m.fortran_vec ()));
1112  retval = m;
1113  break;
1114  }
1115  else
1116  {
1117  int8NDArray m (dims);
1118  mID = jni_env->GetMethodID (cls, "toByte", "()[B");
1119  jbyteArray_ref dv (jni_env, reinterpret_cast<jbyteArray> (jni_env->CallObjectMethod (jobj, mID)));
1120  jni_env->GetByteArrayRegion (dv, 0, m.length (), reinterpret_cast<jbyte *> (m.fortran_vec ()));
1121  retval = m;
1122  break;
1123  }
1124  }
1125  else if (s == "integer")
1126  {
1128  {
1129  uint32NDArray m (dims);
1130  mID = jni_env->GetMethodID (cls, "toInt", "()[I");
1131  jintArray_ref dv (jni_env, reinterpret_cast<jintArray> (jni_env->CallObjectMethod (jobj, mID)));
1132  jni_env->GetIntArrayRegion (dv, 0, m.length (), reinterpret_cast<jint *> (m.fortran_vec ()));
1133  retval = m;
1134  break;
1135  }
1136  else
1137  {
1138  int32NDArray m (dims);
1139  mID = jni_env->GetMethodID (cls, "toInt", "()[I");
1140  jintArray_ref dv (jni_env, reinterpret_cast<jintArray> (jni_env->CallObjectMethod (jobj, mID)));
1141  jni_env->GetIntArrayRegion (dv, 0, m.length (), reinterpret_cast<jint *> (m.fortran_vec ()));
1142  retval = m;
1143  break;
1144  }
1145  }
1146  }
1147  }
1148 
1149  cls = find_octave_class (jni_env, "org/octave/OctaveReference");
1150  if (jni_env->IsInstanceOf (jobj, cls))
1151  {
1152  jmethodID mID = jni_env->GetMethodID (cls, "getID", "()I");
1153  int ID = jni_env->CallIntMethod (jobj, mID);
1154  std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
1155 
1156  if (it != octave_ref_map.end ())
1157  retval = it->second;
1158 
1159  break;
1160  }
1161 
1162  // No suitable class found. Return a generic octave_java object
1163  retval = octave_value (new octave_java (jobj, jcls));
1164  break;
1165  }
1166 
1167  return retval;
1168 }
1169 
1171 box_more (JNIEnv* jni_env, jobject jobj, jclass jcls)
1172 {
1173  octave_value retval = box (jni_env, jobj, jcls);
1174 
1175  if (retval.is_java ())
1176  {
1177  retval = octave_value ();
1178 
1179  jclass_ref cls (jni_env);
1180 
1181  if (retval.is_undefined ())
1182  {
1183  cls = jni_env->FindClass ("[D");
1184 
1185  if (jni_env->IsInstanceOf (jobj, cls))
1186  {
1187  jdoubleArray jarr = reinterpret_cast<jdoubleArray> (jobj);
1188  int len = jni_env->GetArrayLength (jarr);
1189 
1190  if (len > 0)
1191  {
1192  Matrix m (1, len);
1193  jni_env->GetDoubleArrayRegion (jarr, 0, len, m.fortran_vec ());
1194  retval = m;
1195  }
1196  else
1197  retval = Matrix ();
1198  }
1199  }
1200 
1201  if (retval.is_undefined ())
1202  {
1203  cls = jni_env->FindClass ("[[D");
1204 
1205  if (jni_env->IsInstanceOf (jobj, cls))
1206  {
1207  jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);
1208  int rows = jni_env->GetArrayLength (jarr);
1209  int cols = 0;
1210 
1211  if (rows > 0)
1212  {
1213  Matrix m;
1214 
1215  for (int r = 0; r < rows; r++)
1216  {
1217  jdoubleArray_ref row (jni_env,
1218  reinterpret_cast<jdoubleArray> (jni_env->GetObjectArrayElement (jarr, r)));
1219 
1220  if (m.length () == 0)
1221  {
1222  cols = jni_env->GetArrayLength (row);
1223  m.resize (cols, rows);
1224  }
1225  jni_env->GetDoubleArrayRegion (row, 0, cols, m.fortran_vec () + r * cols);
1226  }
1227  retval = m.transpose ();
1228  }
1229  else
1230  retval = Matrix ();
1231  }
1232  }
1233 
1234  if (retval.is_undefined ())
1235  {
1236  cls = jni_env->FindClass ("[Ljava/lang/String;");
1237 
1238  if (jni_env->IsInstanceOf (jobj, cls))
1239  {
1240  jobjectArray jarr = reinterpret_cast<jobjectArray> (jobj);
1241  int len = jni_env->GetArrayLength (jarr);
1242  Cell m (len, 1);
1243 
1244  for (int i = 0; i < len; i++)
1245  {
1246  jstring_ref js (jni_env,
1247  reinterpret_cast<jstring> (jni_env->GetObjectArrayElement (jarr, i)));
1248  m(i) = jstring_to_string (jni_env, js);
1249  }
1250 
1251  retval = m;
1252  }
1253  }
1254  }
1255 
1256  if (retval.is_undefined ())
1257  retval = octave_value (new octave_java (jobj, jcls));
1258 
1259  restore_fpu_state ();
1260 
1261  return retval;
1262 }
1263 
1264 bool
1265 unbox (JNIEnv* jni_env, const octave_value& val, jobject_ref& jobj,
1266  jclass_ref& jcls)
1267 {
1268  bool found = true;
1269 
1270  if (val.is_java ())
1271  {
1272  octave_java *ovj = TO_JAVA (val);
1273  jobj = ovj->to_java ();
1274  jobj.detach ();
1275  jcls = jni_env->GetObjectClass (jobj);
1276  }
1277  else if (val.is_string ())
1278  {
1279  std::string s = val.string_value ();
1280 
1281  jobj = jni_env->NewStringUTF (s.c_str ());
1282  jcls = jni_env->GetObjectClass (jobj);
1283  }
1284  else if (val.numel () > 1 && val.dims ().is_vector ())
1285  {
1286 #define IF_UNBOX_PRIMITIVE_ARRAY(CHECK_TYPE, METHOD_TYPE, OCTAVE_TYPE, JAVA_TYPE, JAVA_TYPE_CAP) \
1287  if (val.is_ ## CHECK_TYPE ## _type ()) \
1288  { \
1289  const OCTAVE_TYPE ## NDArray v = val.METHOD_TYPE ## array_value (); \
1290  JAVA_TYPE ## Array jarr = jni_env->New ## JAVA_TYPE_CAP ## Array (v.numel ()); \
1291  const JAVA_TYPE* jv = reinterpret_cast<const JAVA_TYPE*> (v.data ()); \
1292  jni_env->Set ## JAVA_TYPE_CAP ## ArrayRegion (jarr, 0, v.numel (), jv); \
1293  jobj = reinterpret_cast<jobject> (jarr); \
1294  jcls = jni_env->GetObjectClass (jobj); \
1295  }
1296 
1297  // Note that we do NOT handle char here because they are unboxed
1298  // into a String[], not into a char array
1299  IF_UNBOX_PRIMITIVE_ARRAY(bool, bool_, bool, jboolean, Boolean)
1300  else IF_UNBOX_PRIMITIVE_ARRAY(float, float_, Float, jfloat, Float)
1301  else IF_UNBOX_PRIMITIVE_ARRAY(int8, int8_, int8, jbyte, Byte)
1302  else IF_UNBOX_PRIMITIVE_ARRAY(uint8, uint8_, uint8, jbyte, Byte)
1303  else IF_UNBOX_PRIMITIVE_ARRAY(int16, int16_, int16, jshort, Short)
1304  else IF_UNBOX_PRIMITIVE_ARRAY(uint16, uint16_, uint16, jshort, Short)
1305  else IF_UNBOX_PRIMITIVE_ARRAY(int32, int32_, int32, jint, Int)
1306  else IF_UNBOX_PRIMITIVE_ARRAY(uint32, uint32_, uint32, jint, Int)
1307  else IF_UNBOX_PRIMITIVE_ARRAY(int64, int64_, int64, jlong, Long)
1308  else IF_UNBOX_PRIMITIVE_ARRAY(uint64, uint64_, uint64, jlong, Long)
1309 
1310 #undef IF_UNBOX_PRIMITIVE_ARRAY
1311  }
1312  else if (val.is_real_scalar () || val.is_bool_scalar ())
1313  {
1314 #define IF_UNBOX_PRIMITIVE_SCALAR(CHECK_TYPE, OCTAVE_TYPE, METHOD_TYPE, JAVA_TYPE, JAVA_CON) \
1315  if (val.is_ ## CHECK_TYPE ## _type ()) \
1316  { \
1317  const OCTAVE_TYPE ov = val.METHOD_TYPE ## _value (); \
1318  jclass_ref dcls (jni_env, jni_env->FindClass (JAVA_TYPE)); \
1319  const jfieldID fid = jni_env->GetStaticFieldID (dcls, "TYPE", "Ljava/lang/Class;"); \
1320  const jmethodID mid = jni_env->GetMethodID (dcls, "<init>", JAVA_CON); \
1321  jcls = reinterpret_cast<jclass> (jni_env->GetStaticObjectField (dcls, fid)); \
1322  jobj = jni_env->NewObject (dcls, mid, ov); \
1323  }
1324 
1325  IF_UNBOX_PRIMITIVE_SCALAR(double, double, double, "java/lang/Double", "(D)V")
1326  else IF_UNBOX_PRIMITIVE_SCALAR(float, float, float, "java/lang/Float", "(F)V")
1327  else IF_UNBOX_PRIMITIVE_SCALAR(bool, bool, bool, "java/lang/Boolean", "(Z)V")
1328  else IF_UNBOX_PRIMITIVE_SCALAR(int8, int8_t, int8_scalar, "java/lang/Byte", "(B)V")
1329  else IF_UNBOX_PRIMITIVE_SCALAR(uint8, uint8_t, uint8_scalar, "java/lang/Byte", "(B)V")
1330  else IF_UNBOX_PRIMITIVE_SCALAR(int16, int16_t, int16_scalar, "java/lang/Short", "(S)V")
1331  else IF_UNBOX_PRIMITIVE_SCALAR(uint16, uint16_t, uint16_scalar, "java/lang/Short", "(S)V")
1332  else IF_UNBOX_PRIMITIVE_SCALAR(int32, int32_t, int32_scalar, "java/lang/Int", "(I)V")
1333  else IF_UNBOX_PRIMITIVE_SCALAR(uint32, uint32_t, uint32_scalar, "java/lang/Int", "(I)V")
1334  else IF_UNBOX_PRIMITIVE_SCALAR(int64, int64_t, int64_scalar, "java/lang/Long", "(L)V")
1335  else IF_UNBOX_PRIMITIVE_SCALAR(uint64, uint64_t, uint64_scalar, "java/lang/Long", "(L)V")
1336 
1337 #undef IF_UNBOX_PRIMITIVE_SCALAR
1338  }
1339  else if (val.is_empty ())
1340  {
1341  jobj = 0;
1342  jcls = 0;
1343  //jcls = jni_env->FindClass ("java/lang/Object");
1344  }
1345  else if (!Vjava_matrix_autoconversion
1346  && ((val.is_real_matrix ()
1347  && (val.rows () == 1 || val.columns () == 1))
1348  || val.is_range ()))
1349  {
1350  Matrix m = val.matrix_value ();
1351  jdoubleArray dv = jni_env->NewDoubleArray (m.length ());
1352  jni_env->SetDoubleArrayRegion (dv, 0, m.length (), m.fortran_vec ());
1353  jobj = dv;
1354  jcls = jni_env->GetObjectClass (jobj);
1355  }
1357  && (val.is_matrix_type () || val.is_range ()) && val.is_real_type ())
1358  {
1359  jclass_ref mcls (jni_env, find_octave_class (jni_env, "org/octave/Matrix"));
1360  dim_vector dims = val.dims ();
1361  jintArray_ref iv (jni_env, jni_env->NewIntArray (dims.length ()));
1362  jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), 0);
1363 
1364  for (int i = 0; i < dims.length (); i++)
1365  iv_data[i] = dims(i);
1366 
1367  jni_env->ReleaseIntArrayElements (jintArray (iv), iv_data, 0);
1368 
1369  if (val.is_double_type ())
1370  {
1371  NDArray m = val.array_value ();
1372  jdoubleArray_ref dv (jni_env, jni_env->NewDoubleArray (m.length ()));
1373  jni_env->SetDoubleArrayRegion (jdoubleArray (dv), 0, m.length (),
1374  m.fortran_vec ());
1375  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([D[I)V");
1376  jobj = jni_env->NewObject (jclass (mcls), mID, jdoubleArray (dv),
1377  jintArray (iv));
1378  jcls = jni_env->GetObjectClass (jobj);
1379  }
1380  else if (val.is_int8_type ())
1381  {
1382  int8NDArray m = val.int8_array_value ();
1383  jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.length ()));
1384  jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.length (),
1385  reinterpret_cast <jbyte *> (m.fortran_vec ()));
1386  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
1387  jobj = jni_env->NewObject (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
1388  jcls = jni_env->GetObjectClass (jobj);
1389  }
1390  else if (val.is_uint8_type ())
1391  {
1392  uint8NDArray m = val.uint8_array_value ();
1393  jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.length ()));
1394  jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.length (),
1395  reinterpret_cast<jbyte *> (m.fortran_vec ()));
1396  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
1397  jobj = jni_env->NewObject (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
1398  jcls = jni_env->GetObjectClass (jobj);
1399  }
1400  else if (val.is_int32_type ())
1401  {
1402  int32NDArray m = val.int32_array_value ();
1403  jintArray_ref v (jni_env, jni_env->NewIntArray (m.length ()));
1404  jni_env->SetIntArrayRegion (jintArray (v), 0, m.length (),
1405  reinterpret_cast<jint *> (m.fortran_vec ()));
1406  jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([I[I)V");
1407  jobj = jni_env->NewObject (jclass (mcls), mID, jintArray (v), jintArray (iv));
1408  jcls = jni_env->GetObjectClass (jobj);
1409  }
1410  else
1411  {
1412  found = false;
1413  error ("cannot convert matrix of type '%s'", val.class_name ().c_str ());
1414  }
1415  }
1416  else if (val.is_cellstr ())
1417  {
1418  Cell cellStr = val.cell_value ();
1419  jclass_ref scls (jni_env, jni_env->FindClass ("java/lang/String"));
1420  jobjectArray array = jni_env->NewObjectArray (cellStr.length (), scls, 0);
1421  for (int i = 0; i < cellStr.length (); i++)
1422  {
1423  jstring_ref jstr (jni_env,
1424  jni_env->NewStringUTF (cellStr(i).string_value().c_str ()));
1425  jni_env->SetObjectArrayElement (array, i, jstr);
1426  }
1427  jobj = array;
1428  jcls = jni_env->GetObjectClass (jobj);
1429  }
1430  else
1431  {
1432  jclass rcls = find_octave_class (jni_env, "org/octave/OctaveReference");
1433  jmethodID mID = jni_env->GetMethodID (rcls, "<init>", "(I)V");
1434  int ID = octave_java_refcount++;
1435 
1436  jobj = jni_env->NewObject (rcls, mID, ID);
1437  jcls = rcls;
1438  octave_ref_map[ID] = val;
1439  }
1440 
1441  return found;
1442 }
1443 
1444 bool
1445 unbox (JNIEnv* jni_env, const octave_value_list& args,
1446  jobjectArray_ref& jobjs, jobjectArray_ref& jclss)
1447 {
1448  bool found = true;
1449 
1450  jclass_ref ocls (jni_env, jni_env->FindClass ("java/lang/Object"));
1451  jclass_ref ccls (jni_env, jni_env->FindClass ("java/lang/Class"));
1452 
1453  if (! jobjs)
1454  jobjs = jni_env->NewObjectArray (args.length (), ocls, 0);
1455 
1456  if (! jclss)
1457  jclss = jni_env->NewObjectArray (args.length (), ccls, 0);
1458 
1459  for (int i = 0; i < args.length (); i++)
1460  {
1461  jobject_ref jobj (jni_env);
1462  jclass_ref jcls (jni_env);
1463 
1464  found = unbox (jni_env, args(i), jobj, jcls);
1465  if (! found)
1466  break;
1467 
1468  jni_env->SetObjectArrayElement (jobjs, i, jobj);
1469  jni_env->SetObjectArrayElement (jclss, i, jcls);
1470  }
1471 
1472  return found;
1473 }
1474 
1475 static long
1476 get_current_thread_ID (JNIEnv *jni_env)
1477 {
1478  if (jni_env)
1479  {
1480  jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/Thread"));
1481  jmethodID mID = jni_env->GetStaticMethodID (cls, "currentThread", "()Ljava/lang/Thread;");
1482  jobject_ref jthread (jni_env, jni_env->CallStaticObjectMethod (cls, mID));
1483 
1484  if (jthread)
1485  {
1486  jclass_ref jth_cls (jni_env, jni_env->GetObjectClass (jthread));
1487  mID = jni_env->GetMethodID (jth_cls, "getId", "()J");
1488  long result = jni_env->CallLongMethod (jthread, mID);
1489  //printf ("current java thread ID = %ld\n", result);
1490  return result;
1491  }
1492  }
1493 
1494  return -1;
1495 }
1496 
1497 static int
1498 java_event_hook (void)
1499 {
1500  JNIEnv *current_env = octave_java::thread_jni_env ();
1501 
1502  if (current_env)
1503  {
1504  jclass_ref cls (current_env, find_octave_class (current_env, "org/octave/Octave"));
1505  jmethodID mID = current_env->GetStaticMethodID (cls, "checkPendingAction", "()V");
1506  current_env->CallStaticVoidMethod (cls, mID);
1507 
1508  restore_fpu_state ();
1509  }
1510 
1511  return 0;
1512 }
1513 
1514 static void
1515 initialize_java (void)
1516 {
1517  if (! jvm)
1518  {
1519  try
1520  {
1521  initialize_jvm ();
1522 
1523  JNIEnv *current_env = octave_java::thread_jni_env ();
1524 
1525  command_editor::add_event_hook (java_event_hook);
1526 
1527  octave_thread_ID = get_current_thread_ID (current_env);
1528  //printf ("octave thread ID=%ld\n", octave_thread_ID);
1529  }
1530  catch (std::string msg)
1531  {
1532  error (msg.c_str ());
1533  }
1534 
1535  restore_fpu_state ();
1536  }
1537 }
1538 
1539 JNIEXPORT jboolean JNICALL
1540 Java_org_octave_Octave_call (JNIEnv *env, jclass, jstring funcName,
1541  jobjectArray argin, jobjectArray argout)
1542 {
1543  std::string fname = jstring_to_string (env, funcName);
1544 
1545  int nargout = env->GetArrayLength (argout);
1546  int nargin = env->GetArrayLength (argin);
1547 
1548  octave_value_list varargin, varargout;
1549 
1550  for (int i = 0; i < nargin; i++)
1551  varargin(i) = box (env, env->GetObjectArrayElement (argin, i), 0);
1552 
1553  varargout = feval (fname, varargin, nargout);
1554  if (error_state)
1555  return false;
1556 
1557  jobjectArray_ref out_objs (env, argout), out_clss (env);
1558  out_objs.detach ();
1559  return unbox (env, varargout, out_objs, out_clss);
1560 }
1561 
1562 JNIEXPORT void JNICALL
1563 Java_org_octave_OctaveReference_doFinalize (JNIEnv *, jclass, jint ID)
1564 {
1565  octave_ref_map.erase (ID);
1566 }
1567 
1568 JNIEXPORT void JNICALL
1569 Java_org_octave_Octave_doInvoke (JNIEnv *env, jclass, jint ID,
1570  jobjectArray args)
1571 {
1572  std::map<int,octave_value>::iterator it = octave_ref_map.find (ID);
1573 
1574  if (it != octave_ref_map.end ())
1575  {
1576  octave_value val = it->second;
1577  int len = env->GetArrayLength (args);
1578  octave_value_list oct_args;
1579 
1580  for (int i = 0; i < len; i++)
1581  {
1582  jobject_ref jobj (env, env->GetObjectArrayElement (args, i));
1583  oct_args(i) = box (env, jobj, 0);
1584 
1585  if (error_state)
1586  break;
1587  }
1588 
1589  if (! error_state)
1590  {
1591  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
1592 
1593  if (val.is_function_handle ())
1594  {
1595  octave_function *fcn = val.function_value ();
1596  feval (fcn, oct_args);
1597  }
1598  else if (val.is_cell () && val.length () > 0
1599  && (val.rows () == 1 || val.columns () == 1)
1600  && val.cell_value()(0).is_function_handle ())
1601  {
1602  Cell c = val.cell_value ();
1603  octave_function *fcn = c(0).function_value ();
1604 
1605  for (int i=1; i<c.length (); i++)
1606  oct_args(len+i-1) = c(i);
1607 
1608  if (! error_state)
1609  feval (fcn, oct_args);
1610  }
1611  else
1612  error ("trying to invoke non-invocable object");
1613 
1614  END_INTERRUPT_WITH_EXCEPTIONS;
1615  }
1616  }
1617 }
1618 
1619 JNIEXPORT void JNICALL
1620 Java_org_octave_Octave_doEvalString (JNIEnv *env, jclass, jstring cmd)
1621 {
1622  std::string s = jstring_to_string (env, cmd);
1623  int pstatus;
1624  eval_string (s, false, pstatus, 0);
1625 }
1626 
1627 JNIEXPORT jboolean JNICALL
1628 Java_org_octave_Octave_needThreadedInvokation (JNIEnv *env, jclass)
1629 {
1630  return (get_current_thread_ID (env) != octave_thread_ID);
1631 }
1632 
1633 // octave_java class definition
1634 
1635 
1636 int octave_java::t_id (-1);
1637 
1638 const std::string octave_java::t_name ("octave_java");
1639 
1640 void
1642 {
1644  (octave_java::t_name, "<unknown>", octave_value (new octave_java ()));
1645 }
1646 
1647 dim_vector
1648 octave_java::dims (void) const
1649 {
1650  JNIEnv *current_env = thread_jni_env ();
1651 
1652  if (current_env && java_object)
1653  return compute_array_dimensions (current_env, java_object);
1654  else
1655  return dim_vector (1, 1);
1656 }
1657 
1658 JNIEnv *
1660 {
1661  JNIEnv *env = 0;
1662 
1663  if (jvm)
1664  jvm->GetEnv (reinterpret_cast<void **> (&env), JNI_VERSION_1_2);
1665 
1666  return env;
1667 }
1668 
1670 octave_java::subsref (const std::string& type,
1671  const std::list<octave_value_list>& idx, int nargout)
1672 {
1673  octave_value_list retval;
1674  int skip = 1;
1675 
1676  JNIEnv *current_env = thread_jni_env ();
1677 
1678  switch (type[0])
1679  {
1680  case '.':
1681  if (type.length () > 1 && type[1] == '(')
1682  {
1684  count++;
1685  ovl(1) = octave_value (this);
1686  ovl(0) = (idx.front ())(0);
1687  std::list<octave_value_list>::const_iterator it = idx.begin ();
1688  ovl.append (*++it);
1689  retval = feval (std::string ("javaMethod"), ovl, 1);
1690  skip++;
1691  }
1692  else
1693  {
1695  count++;
1696  ovl(0) = octave_value (this);
1697  ovl(1) = (idx.front ())(0);
1698  retval = feval (std::string ("__java_get__"), ovl, 1);
1699  }
1700  break;
1701 
1702  case '(':
1703  if (current_env)
1704  retval = get_array_elements (current_env, to_java (), idx.front ());
1705  break;
1706 
1707  default:
1708  error ("subsref: Java object cannot be indexed with %c", type[0]);
1709  break;
1710  }
1711 
1712  if (idx.size () > 1 && type.length () > 1)
1713  retval = retval(0).next_subsref (nargout, type, idx, skip);
1714 
1715  return retval;
1716 }
1717 
1719 octave_java::subsasgn (const std::string& type,
1720  const std::list<octave_value_list>&idx,
1721  const octave_value &rhs)
1722 {
1723  octave_value retval;
1724 
1725  JNIEnv *current_env = thread_jni_env ();
1726 
1727  switch (type[0])
1728  {
1729  case '.':
1730  if (type.length () == 1)
1731  {
1732  // field assignment
1734  count++;
1735  ovl(0) = octave_value (this);
1736  ovl(1) = (idx.front ())(0);
1737  ovl(2) = rhs;
1738  feval ("__java_set__", ovl, 0);
1739  if (! error_state)
1740  {
1741  count++;
1742  retval = octave_value (this);
1743  }
1744  }
1745  else if (type.length () > 2 && type[1] == '(')
1746  {
1747  std::list<octave_value_list> new_idx;
1748  std::list<octave_value_list>::const_iterator it = idx.begin ();
1749  new_idx.push_back (*it++);
1750  new_idx.push_back (*it++);
1751  octave_value_list u = subsref (type.substr (0, 2), new_idx, 1);
1752  if (! error_state)
1753  {
1754  std::list<octave_value_list> next_idx (idx);
1755  next_idx.erase (next_idx.begin ());
1756  next_idx.erase (next_idx.begin ());
1757  u(0).subsasgn (type.substr (2), next_idx, rhs);
1758  if (! error_state)
1759  {
1760  count++;
1761  retval = octave_value (this);
1762  }
1763  }
1764  }
1765  else if (type[1] == '.')
1766  {
1767  octave_value_list u = subsref (type.substr (0, 1), idx, 1);
1768  if (! error_state)
1769  {
1770  std::list<octave_value_list> next_idx (idx);
1771  next_idx.erase (next_idx.begin ());
1772  u(0).subsasgn (type.substr (1), next_idx, rhs);
1773  if (! error_state)
1774  {
1775  count++;
1776  retval = octave_value (this);
1777  }
1778  }
1779  }
1780  else
1781  error ("invalid indexing/assignment on Java object");
1782  break;
1783 
1784  case '(':
1785  if (current_env)
1786  {
1787  set_array_elements (current_env, to_java (), idx.front (), rhs);
1788  if (! error_state)
1789  {
1790  count++;
1791  retval = octave_value (this);
1792  }
1793  }
1794  break;
1795 
1796  default:
1797  error ("Java object cannot be indexed with %c", type[0]);
1798  break;
1799  }
1800 
1801  return retval;
1802 }
1803 
1805 octave_java::map_keys (void) const
1806 {
1807  JNIEnv *current_env = thread_jni_env ();
1808 
1809  if (current_env)
1810  return get_invoke_list (current_env, to_java ());
1811  else
1812  return string_vector ();
1813 }
1814 
1816 octave_java::convert_to_str_internal (bool, bool force, char type) const
1817 {
1818  JNIEnv *current_env = thread_jni_env ();
1819 
1820  if (current_env)
1821  return convert_to_string (current_env, to_java (), force, type);
1822  else
1823  return octave_value ("");
1824 }
1825 
1826 void
1827 octave_java::print (std::ostream& os, bool)
1828 {
1829  print_raw (os);
1830  newline (os);
1831 }
1832 
1833 void
1834 octave_java::print_raw (std::ostream& os, bool) const
1835 {
1836  os << "<Java object: " << java_classname << ">";
1837 }
1838 
1840 octave_java::do_javaMethod (JNIEnv* jni_env, const std::string& name,
1841  const octave_value_list& args)
1842 {
1843  octave_value retval;
1844 
1845  if (jni_env)
1846  {
1847  jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);
1848  if (unbox (jni_env, args, arg_objs, arg_types))
1849  {
1850  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
1851  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeMethod",
1852  "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;");
1853  jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ()));
1854  jobjectArray_ref resObj (jni_env, reinterpret_cast<jobjectArray> (jni_env->CallStaticObjectMethod (helperClass, mID,
1855  to_java (), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types))));
1856  if (resObj)
1857  retval = box (jni_env, resObj);
1858  else
1859  retval = check_exception (jni_env);
1860  }
1861 
1862  restore_fpu_state ();
1863  }
1864 
1865  return retval;
1866 }
1867 
1869 octave_java:: do_javaMethod (JNIEnv* jni_env,
1870  const std::string& class_name,
1871  const std::string& name,
1872  const octave_value_list& args)
1873 {
1874  octave_value retval;
1875 
1876  if (jni_env)
1877  {
1878  jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);
1879  if (unbox (jni_env, args, arg_objs, arg_types))
1880  {
1881  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
1882  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeStaticMethod",
1883  "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;");
1884  jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ()));
1885  jstring_ref clsName (jni_env, jni_env->NewStringUTF (class_name.c_str ()));
1886  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
1887  jstring (clsName), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types)));
1888  if (resObj)
1889  retval = box (jni_env, resObj);
1890  else
1891  retval = check_exception (jni_env);
1892  }
1893 
1894  restore_fpu_state ();
1895  }
1896 
1897  return retval;
1898 }
1899 
1901 octave_java::do_javaObject (JNIEnv* jni_env, const std::string& name,
1902  const octave_value_list& args)
1903 {
1904  octave_value retval;
1905 
1906  if (jni_env)
1907  {
1908  jobjectArray_ref arg_objs (jni_env), arg_types (jni_env);
1909 
1910  if (unbox (jni_env, args, arg_objs, arg_types))
1911  {
1912  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
1913  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeConstructor",
1914  "(Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;");
1915  jstring_ref clsName (jni_env, jni_env->NewStringUTF (name.c_str ()));
1916  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
1917  jstring (clsName), jobjectArray (arg_objs), jobjectArray (arg_types)));
1918 
1919  if (resObj)
1920  retval = octave_value (new octave_java (resObj, 0));
1921  else
1922  check_exception (jni_env);
1923  }
1924 
1925  restore_fpu_state ();
1926  }
1927 
1928  return retval;
1929 }
1930 
1932 octave_java::do_java_get (JNIEnv* jni_env, const std::string& name)
1933 {
1934  octave_value retval;
1935 
1936  if (jni_env)
1937  {
1938  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
1939  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "getField",
1940  "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;");
1941  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
1942  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
1943  to_java (), jstring (fName)));
1944 
1945  if (resObj)
1946  retval = box (jni_env, resObj);
1947  else
1948  retval = check_exception (jni_env);
1949 
1950  restore_fpu_state ();
1951  }
1952 
1953  return retval;
1954 }
1955 
1957 octave_java::do_java_get (JNIEnv* jni_env, const std::string& class_name,
1958  const std::string& name)
1959 {
1960  octave_value retval;
1961 
1962  if (jni_env)
1963  {
1964  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
1965  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "getStaticField",
1966  "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
1967  jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ()));
1968  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
1969  jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID,
1970  jstring (cName), jstring (fName)));
1971  if (resObj)
1972  retval = box (jni_env, resObj);
1973  else
1974  retval = check_exception (jni_env);
1975 
1976  restore_fpu_state ();
1977  }
1978 
1979  return retval;
1980 }
1981 
1983 octave_java::do_java_set (JNIEnv* jni_env, const std::string& name,
1984  const octave_value& val)
1985 {
1986  octave_value retval;
1987 
1988  if (jni_env)
1989  {
1990  jobject_ref jobj (jni_env);
1991  jclass_ref jcls (jni_env);
1992 
1993  if (unbox (jni_env, val, jobj, jcls))
1994  {
1995  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
1996  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "setField",
1997  "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V");
1998  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
1999  jni_env->CallStaticObjectMethod (helperClass, mID, to_java (), jstring (fName), jobject (jobj));
2000  check_exception (jni_env);
2001  }
2002 
2003  restore_fpu_state ();
2004  }
2005 
2006  return retval;
2007 }
2008 
2010 octave_java::do_java_set (JNIEnv* jni_env, const std::string& class_name,
2011  const std::string& name, const octave_value& val)
2012 {
2013  octave_value retval;
2014 
2015  if (jni_env)
2016  {
2017  jobject_ref jobj (jni_env);
2018  jclass_ref jcls (jni_env);
2019 
2020  if (unbox (jni_env, val, jobj, jcls))
2021  {
2022  jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper"));
2023  jmethodID mID = jni_env->GetStaticMethodID (helperClass, "setStaticField",
2024  "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V");
2025  jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ()));
2026  jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ()));
2027  jni_env->CallStaticObjectMethod (helperClass, mID, jstring (cName), jstring (fName), jobject (jobj));
2028  check_exception (jni_env);
2029  }
2030 
2031  restore_fpu_state ();
2032  }
2033 
2034  return retval;
2035 }
2036 
2037 #endif // endif on HAVE_JAVA
2038 
2039 // DEFUN blocks below must be outside of HAVE_JAVA block so that
2040 // documentation strings are always available, even when functions are not.
2041 
2042 DEFUN (__java_init__, , ,
2043  "-*- texinfo -*-\n\
2044 @deftypefn {Built-in Function} {} __java_init__ ()\n\
2045 Internal function used @strong{only} when debugging Java interface.\n\
2046 \n\
2047 Function will directly call initialize_java() to create an instance of a JVM.\n\
2048 @end deftypefn")
2049 {
2050 
2051 #ifdef HAVE_JAVA
2052  octave_value retval;
2053 
2054  retval = 0;
2055 
2056  initialize_java ();
2057 
2058  if (! error_state)
2059  retval = 1;
2060 
2061  return retval;
2062 #else
2063  error ("__java_init__: Octave was not compiled with Java interface");
2064  return octave_value ();
2065 #endif
2066 }
2067 
2068 DEFUN (__java_exit__, , ,
2069  "-*- texinfo -*-\n\
2070 @deftypefn {Built-in Function} {} __java_exit__ ()\n\
2071 Internal function used @strong{only} when debugging Java interface.\n\
2072 \n\
2073 Function will directly call terminate_jvm() to destroy the current JVM\n\
2074 instance.\n\
2075 @end deftypefn")
2076 {
2077 #ifdef HAVE_JAVA
2078  terminate_jvm ();
2079 #else
2080  error ("__java_init__: Octave was not compiled with Java interface");
2081 #endif
2082 
2083  return octave_value ();
2084 }
2085 
2086 DEFUN (javaObject, args, ,
2087  "-*- texinfo -*-\n\
2088 @deftypefn {Built-in Function} {@var{jobj} =} javaObject (@var{classname})\n\
2089 @deftypefnx {Built-in Function} {@var{jobj} =} javaObject (@var{classname}, @var{arg1}, @dots{})\n\
2090 Create a Java object of class @var{classsname}, by calling the class\n\
2091 constructor with the arguments @var{arg1}, @dots{}\n\
2092 \n\
2093 The first example below creates an uninitialized object, while the second\n\
2094 example supplies an initial argument to the constructor.\n\
2095 \n\
2096 @example\n\
2097 @group\n\
2098 x = javaObject (\"java.lang.StringBuffer\")\n\
2099 x = javaObject (\"java.lang.StringBuffer\", \"Initial string\")\n\
2100 @end group\n\
2101 @end example\n\
2102 \n\
2103 @seealso{javaMethod, javaArray}\n\
2104 @end deftypefn")
2105 {
2106 #ifdef HAVE_JAVA
2107  octave_value retval;
2108 
2109  initialize_java ();
2110 
2111  if (! error_state)
2112  {
2113  JNIEnv *current_env = octave_java::thread_jni_env ();
2114 
2115  if (args.length () > 0)
2116  {
2117  if (args(0).is_string ())
2118  {
2119  std::string classname = args(0).string_value ();
2120 
2121  octave_value_list tmp;
2122  for (int i=1; i<args.length (); i++)
2123  tmp(i-1) = args(i);
2124  retval = octave_java::do_javaObject (current_env, classname, tmp);
2125  }
2126  else
2127  error ("javaObject: CLASSNAME must be a string");
2128  }
2129  else
2130  print_usage ();
2131  }
2132 
2133  return retval;
2134 #else
2135  error ("javaObject: Octave was not compiled with Java interface");
2136  return octave_value ();
2137 #endif
2138 }
2139 
2140 /*
2141 ## The tests below merely check if javaObject() works at all. Whether it works
2142 ## properly, i.e., creates the right values, is a matter of Java itself.
2143 ## Create a Short and check if it really is a short, i.e., whether it overflows.
2144 %!testif HAVE_JAVA
2145 %! assert (javaObject ("java.lang.Short", 40000).doubleValue < 0);
2146 */
2147 
2148 DEFUN (javaMethod, args, ,
2149  "-*- texinfo -*-\n\
2150 @deftypefn {Built-in Function} {@var{ret} =} javaMethod (@var{methodname}, @var{obj})\n\
2151 @deftypefnx {Built-in Function} {@var{ret} =} javaMethod (@var{methodname}, @var{obj}, @var{arg1}, @dots{})\n\
2152 Invoke the method @var{methodname} on the Java object @var{obj} with the\n\
2153 arguments @var{arg1}, @dots{}.\n\
2154 \n\
2155 For static methods, @var{obj} can be a string representing the fully\n\
2156 qualified name of the corresponding class.\n\
2157 \n\
2158 When @var{obj} is a regular Java object, structure-like indexing can be\n\
2159 used as a shortcut syntax. For instance, the two following statements are\n\
2160 equivalent\n\
2161 \n\
2162 @example\n\
2163 @group\n\
2164  ret = javaMethod (\"method1\", x, 1.0, \"a string\")\n\
2165  ret = x.method1 (1.0, \"a string\")\n\
2166 @end group\n\
2167 @end example\n\
2168 \n\
2169 @code{javaMethod} returns the result of the method invocation.\n\
2170 \n\
2171 @seealso{methods, javaObject}\n\
2172 @end deftypefn")
2173 {
2174 #ifdef HAVE_JAVA
2175  octave_value retval;
2176 
2177  initialize_java ();
2178 
2179  if (! error_state)
2180  {
2181  JNIEnv *current_env = octave_java::thread_jni_env ();
2182 
2183  if (args.length () > 1)
2184  {
2185  if (args(0).is_string ())
2186  {
2187  std::string methodname = args(0).string_value ();
2188 
2189  octave_value_list tmp;
2190  for (int i=2; i<args.length (); i++)
2191  tmp(i-2) = args(i);
2192 
2193  if (args(1).is_java ())
2194  {
2195  octave_java *jobj = TO_JAVA (args(1));
2196  retval = jobj->do_javaMethod (current_env, methodname, tmp);
2197  }
2198  else if (args(1).is_string ())
2199  {
2200  std::string cls = args(1).string_value ();
2201  retval = octave_java::do_javaMethod (current_env, cls, methodname, tmp);
2202  }
2203  else
2204  error ("javaMethod: OBJ must be a Java object or a string");
2205  }
2206  else
2207  error ("javaMethod: METHODNAME must be a string");
2208  }
2209  else
2210  print_usage ();
2211  }
2212 
2213  return retval;
2214 #else
2215  error ("javaMethod: Octave was not compiled with Java interface");
2216  return octave_value ();
2217 #endif
2218 }
2219 
2220 /*
2221 %!testif HAVE_JAVA
2222 %! ## Check for valid first two Java version numbers
2223 %! jver = strsplit (javaMethod ("getProperty", "java.lang.System", "java.version"), ".");
2224 %! assert (isfinite (str2double (jver{1})) && isfinite (str2double (jver{2})));
2225 */
2226 
2227 DEFUN (__java_get__, args, ,
2228  "-*- texinfo -*-\n\
2229 @deftypefn {Built-in Function} {@var{val} =} __java_get__ (@var{obj}, @var{name})\n\
2230 Get the value of the field @var{name} of the Java object @var{obj}.\n\
2231 \n\
2232 For static fields, @var{obj} can be a string representing the fully qualified\n\
2233 name of the corresponding class.\n\
2234 \n\
2235 When @var{obj} is a regular Java object, structure-like indexing can be used\n\
2236 as a shortcut syntax. For instance, the two following statements are\n\
2237 equivalent\n\
2238 \n\
2239 @example\n\
2240 @group\n\
2241  __java_get__ (x, \"field1\")\n\
2242  x.field1\n\
2243 @end group\n\
2244 @end example\n\
2245 \n\
2246 @seealso{__java_set__, javaMethod, javaObject}\n\
2247 @end deftypefn")
2248 {
2249 #ifdef HAVE_JAVA
2250  octave_value retval;
2251 
2252  initialize_java ();
2253 
2254  if (! error_state)
2255  {
2256  JNIEnv *current_env = octave_java::thread_jni_env ();
2257 
2258  if (args.length () == 2)
2259  {
2260  if (args(1).is_string ())
2261  {
2262  std::string name = args(1).string_value ();
2263 
2264  if (args(0).is_java ())
2265  {
2266  octave_java *jobj = TO_JAVA (args(0));
2267  retval = jobj->do_java_get (current_env, name);
2268  }
2269  else if (args(0).is_string ())
2270  {
2271  std::string cls = args(0).string_value ();
2272  retval = octave_java::do_java_get (current_env, cls, name);
2273  }
2274  else
2275  error ("__java_get__: OBJ must be a Java object or a string");
2276  }
2277  else
2278  error ("__java_get__: NAME must be a string");
2279  }
2280  else
2281  print_usage ();
2282  }
2283 
2284  return retval;
2285 #else
2286  error ("__java_get__: Octave was not compiled with Java interface");
2287  return octave_value ();
2288 #endif
2289 }
2290 
2291 DEFUN (__java_set__, args, ,
2292  "-*- texinfo -*-\n\
2293 @deftypefn {Built-in Function} {@var{obj} =} __java_set__ (@var{obj}, @var{name}, @var{val})\n\
2294 Set the value of the field @var{name} of the Java object @var{obj} to\n\
2295 @var{val}.\n\
2296 \n\
2297 For static fields, @var{obj} can be a string representing the fully\n\
2298 qualified named of the corresponding Java class.\n\
2299 \n\
2300 When @var{obj} is a regular Java object, structure-like indexing can be\n\
2301 used as a shortcut syntax. For instance, the two following statements are\n\
2302 equivalent\n\
2303 \n\
2304 @example\n\
2305 @group\n\
2306  __java_set__ (x, \"field1\", val)\n\
2307  x.field1 = val\n\
2308 @end group\n\
2309 @end example\n\
2310 \n\
2311 @seealso{__java_get__, javaMethod, javaObject}\n\
2312 @end deftypefn")
2313 {
2314 #ifdef HAVE_JAVA
2315  octave_value retval;
2316 
2317  initialize_java ();
2318 
2319  if (! error_state)
2320  {
2321  JNIEnv *current_env = octave_java::thread_jni_env ();
2322 
2323  if (args.length () == 3)
2324  {
2325  if (args(1).is_string ())
2326  {
2327  std::string name = args(1).string_value ();
2328 
2329  if (args(0).is_java ())
2330  {
2331  octave_java *jobj = TO_JAVA (args(0));
2332  retval = jobj->do_java_set (current_env, name, args(2));
2333  }
2334  else if (args(0).is_string ())
2335  {
2336  std::string cls = args(0).string_value ();
2337  retval = octave_java::do_java_set (current_env, cls, name, args(2));
2338  }
2339  else
2340  error ("__java_set__: OBJ must be a Java object or a string");
2341  }
2342  else
2343  error ("__java_set__: NAME must be a string");
2344  }
2345  else
2346  print_usage ();
2347  }
2348 
2349  return retval;
2350 #else
2351  error ("__java_set__: Octave was not compiled with Java interface");
2352  return octave_value ();
2353 #endif
2354 }
2355 
2356 DEFUN (java2mat, args, ,
2357  "-*- texinfo -*-\n\
2358 @deftypefn {Built-in Function} {} java2mat (@var{javaobj})\n\
2359 Undocumented internal function.\n\
2360 @end deftypefn")
2361 {
2362 #ifdef HAVE_JAVA
2363  octave_value_list retval;
2364 
2365  initialize_java ();
2366 
2367  if (! error_state)
2368  {
2369  JNIEnv *current_env = octave_java::thread_jni_env ();
2370 
2371  if (args.length () == 1)
2372  {
2373  if (args(0).is_java ())
2374  {
2375  octave_java *jobj = TO_JAVA (args(0));
2376  retval(0) = box_more (current_env, jobj->to_java (), 0);
2377  }
2378  else
2379  retval(0) = args(0);
2380  }
2381  else
2382  print_usage ();
2383  }
2384 
2385  return retval;
2386 #else
2387  error ("java2mat: Octave was not compiled with Java interface");
2388  return octave_value ();
2389 #endif
2390 }
2391 
2392 DEFUN (java_matrix_autoconversion, args, nargout,
2393  "-*- texinfo -*-\n\
2394 @deftypefn {Built-in Function} {@var{val} =} java_matrix_autoconversion ()\n\
2395 @deftypefnx {Built-in Function} {@var{old_val} =} java_matrix_autoconversion (@var{new_val})\n\
2396 @deftypefnx {Built-in Function} {} java_matrix_autoconversion (@var{new_val}, \"local\")\n\
2397 Query or set the internal variable that controls whether Java arrays are\n\
2398 automatically converted to Octave matrices.\n\
2399 \n\
2400 The default value is false.\n\
2401 \n\
2402 When called from inside a function with the @qcode{\"local\"} option, the\n\
2403 variable is changed locally for the function and any subroutines it calls.\n\
2404 The original variable value is restored when exiting the function.\n\
2405 @seealso{java_unsigned_autoconversion, debug_java}\n\
2406 @end deftypefn")
2407 {
2408 #ifdef HAVE_JAVA
2409  return SET_INTERNAL_VARIABLE (java_matrix_autoconversion);
2410 #else
2411  error ("java_matrix_autoconversion: Octave was not compiled with Java interface");
2412  return octave_value ();
2413 #endif
2414 }
2415 
2416 DEFUN (java_unsigned_autoconversion, args, nargout,
2417  "-*- texinfo -*-\n\
2418 @deftypefn {Built-in Function} {@var{val} =} java_unsigned_autoconversion ()\n\
2419 @deftypefnx {Built-in Function} {@var{old_val} =} java_unsigned_autoconversion (@var{new_val})\n\
2420 @deftypefnx {Built-in Function} {} java_unsigned_autoconversion (@var{new_val}, \"local\")\n\
2421 Query or set the internal variable that controls how integer classes are\n\
2422 converted when @code{java_matrix_autoconversion} is enabled.\n\
2423 \n\
2424 When enabled, Java arrays of class Byte or Integer are converted to matrices\n\
2425 of class uint8 or uint32 respectively. The default value is true.\n\
2426 \n\
2427 When called from inside a function with the @qcode{\"local\"} option, the\n\
2428 variable is changed locally for the function and any subroutines it calls.\n\
2429 The original variable value is restored when exiting the function.\n\
2430 @seealso{java_matrix_autoconversion, debug_java}\n\
2431 @end deftypefn")
2432 {
2433 #ifdef HAVE_JAVA
2434  return SET_INTERNAL_VARIABLE (java_unsigned_autoconversion);
2435 #else
2436  error ("java_unsigned_autoconversion: Octave was not compiled with Java interface");
2437  return octave_value ();
2438 #endif
2439 }
2440 
2441 DEFUN (debug_java, args, nargout,
2442  "-*- texinfo -*-\n\
2443 @deftypefn {Built-in Function} {@var{val} =} debug_java ()\n\
2444 @deftypefnx {Built-in Function} {@var{old_val} =} debug_java (@var{new_val})\n\
2445 @deftypefnx {Built-in Function} {} debug_java (@var{new_val}, \"local\")\n\
2446 Query or set the internal variable that determines whether extra debugging\n\
2447 information regarding the initialization of the JVM and any Java exceptions\n\
2448 is printed.\n\
2449 \n\
2450 When called from inside a function with the @qcode{\"local\"} option, the\n\
2451 variable is changed locally for the function and any subroutines it calls.\n\
2452 The original variable value is restored when exiting the function.\n\
2453 @seealso{java_matrix_autoconversion, java_unsigned_autoconversion}\n\
2454 @end deftypefn")
2455 {
2456 #ifdef HAVE_JAVA
2457  return SET_INTERNAL_VARIABLE (debug_java);
2458 #else
2459  error ("debug_java: Octave was not compiled with Java interface");
2460  return octave_value ();
2461 #endif
2462 }
2463 
2464 // Outside of #ifdef HAVE_JAVA because it is desirable to be able to
2465 // test for the presence of a Java object without having Java installed.
2466 DEFUN (isjava, args, ,
2467  "-*- texinfo -*-\n\
2468 @deftypefn {Built-in Function} {} isjava (@var{x})\n\
2469 Return true if @var{x} is a Java object.\n\
2470 @seealso{class, typeinfo, isa, javaObject}\n\
2471 @end deftypefn")
2472 {
2473  octave_value retval;
2474 
2475  if (args.length () != 1)
2476  print_usage ();
2477  else
2478  retval = args(0).is_java ();
2479 
2480  return retval;
2481 }
2482 
2483 /*
2484 ## Check automatic conversion of java primitive arrays into octave types.
2485 %!testif HAVE_JAVA
2486 %! assert (javaObject ("java.lang.String", "hello").getBytes (),
2487 %! int8 ([104 101 108 108 111]'));
2488 
2489 ## Check automatic conversion of octave types into java primitive arrays.
2490 ## Note that uint8 is casted to int8.
2491 %!testif HAVE_JAVA
2492 %! assert (javaMethod ("binarySearch", "java.util.Arrays", [90 100 255], 255), 2);
2493 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint8 ([90 100 255]), uint8 (255)) < 0);
2494 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint8 ([90 100 128]), uint8 (128)) < 0);
2495 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint8 ([90 100 127]), uint8 (127)), 2);
2496 %! assert (javaMethod ("binarySearch", "java.util.Arrays", uint16 ([90 100 128]), uint16 (128)), 2);
2497 
2498 ## Check we can create objects that wrap java literals (bug #38821).
2499 %!testif HAVE_JAVA
2500 %! assert (class (javaObject ("java.lang.Byte", uint8 (1))), "java.lang.Byte");
2501 %! assert (class (javaObject ("java.lang.Byte", int8 (1))), "java.lang.Byte");
2502 %! assert (class (javaObject ("java.lang.Short", uint16 (1))), "java.lang.Short");
2503 %! assert (class (javaObject ("java.lang.Short", int16 (1))), "java.lang.Short");
2504 */
uint8NDArray uint8_array_value(void) const
Definition: ov.h:882
jobject java_object
Definition: ov-java.h:295
bool is_range(void) const
Definition: ov.h:571
static void register_type(void)
Definition: Cell.h:35
octave_idx_type length(octave_idx_type n=0) const
Definition: idx-vector.h:551
static JNIEnv * thread_jni_env(void)
octave_refcount< octave_idx_type > count
Definition: ov-base.h:818
bool is_real_type(void) const
Definition: ov.h:651
#define C(a, b)
Definition: Faddeeva.cc:255
octave_idx_type rows(void) const
Definition: ov.h:473
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:130
int8NDArray int8_array_value(void) const
Definition: ov.h:870
bool is_vector(void) const
Definition: dim-vector.h:430
static std::string path_sep_str(void)
Definition: pathsearch.h:95
octave_value do_java_set(JNIEnv *jni_env, const std::string &name, const octave_value &val)
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
OCTINTERP_API octave_value box(JNIEnv *jni_env, jobject jobj, jclass jcls=0)
octave_idx_type length(void) const
Definition: oct-obj.h:89
octave_value_list & append(const octave_value &val)
Definition: oct-obj.cc:85
OCTINTERP_API bool Vjava_unsigned_autoconversion
static char * strsave(const char *s)
Definition: main.cc:414
void resize(int n, int fill_value=0)
Definition: dim-vector.h:287
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
static void add_event_hook(event_hook_fcn f)
Definition: cmd-edit.cc:1440
int32NDArray int32_array_value(void) const
Definition: ov.h:876
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:120
bool is_int8_type(void) const
Definition: ov.h:619
octave_value_list feval(const std::string &name, const octave_value_list &args, int nargout)
Definition: oct-parse.cc:8625
std::string Vfcn_file_dir
Definition: defaults.cc:82
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
void detach(void)
Definition: ov-java.h:55
bool is_cell(void) const
Definition: ov.h:529
octave_value_list eval_string(const std::string &eval_str, bool silent, int &parse_status, int nargout)
Definition: oct-parse.cc:8810
F77_RET_T const octave_idx_type const octave_idx_type const octave_idx_type double const octave_idx_type double const octave_idx_type double const octave_idx_type double * Z
Definition: qz.cc:114
bool is_int32_type(void) const
Definition: ov.h:625
void newline(std::ostream &os) const
Definition: ov-base.cc:1500
bool is_function_handle(void) const
Definition: ov.h:686
OCTINTERP_API std::string jstring_to_string(JNIEnv *jni_env, jstring s)
static std::string tilde_expand(const std::string &)
Definition: file-ops.cc:286
Cell cell_value(void) const
Definition: ov.cc:1566
octave_idx_type columns(void) const
Definition: ov.h:475
jobject to_java(void) const
Definition: ov-java.h:134
static void replace(QString &text, const QRegExp &re, const QString &after)
Definition: parser.cc:566
octave_value convert_to_str(bool pad=false, bool force=false, char type= '\'') const
Definition: ov.h:1017
static std::string get_current_directory(void)
Definition: oct-env.cc:139
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:395
bool is_real_scalar(void) const
Definition: ov.h:535
std::string string_value(bool force=false) const
Definition: ov.h:897
static bool chdir(const std::string &newdir)
Definition: oct-env.cc:259
bool is_matrix_type(void) const
Definition: ov.h:660
bool is_string(void) const
Definition: ov.h:562
bool is_double_type(void) const
Definition: ov.h:608
int error_state
Definition: error.cc:101
static std::string getenv(const std::string &name)
Definition: oct-env.cc:238
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
bool is_cellstr(void) const
Definition: ov.h:532
Matrix transpose(void) const
Definition: dMatrix.h:114
dim_vector dims(void) const
octave_idx_type length(void) const
Definition: ov.cc:1525
Definition: dMatrix.h:35
dim_vector dims(void) const
Definition: ov.h:470
void sort(bool uniq=false)
Definition: idx-vector.h:1038
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:773
friend class octave_value
Definition: ov-base.h:206
OCTINTERP_API bool Vdebug_java
octave_function * function_value(bool silent=false) const
Definition: ov.cc:1597
OCTINTERP_API bool unbox(JNIEnv *jni_env, const octave_value &val, jobject_ref &jobj, jclass_ref &jcls)
static const std::string t_name
Definition: ov-java.h:314
octave_value do_javaMethod(JNIEnv *jni_env, const std::string &name, const octave_value_list &args)
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
bool is_empty(void) const
Definition: ov.h:526
bool is_bool_scalar(void) const
Definition: ov.h:547
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:779
octave_value_list ovl(const octave_value &a0)
Definition: oct-obj.h:178
F77_RET_T const octave_idx_type Complex const octave_idx_type Complex * B
Definition: CmplxGEPBAL.cc:39
void print(std::ostream &os, bool pr_as_read_syntax=false)
bool is_java_string(void) const
F77_RET_T const octave_idx_type const octave_idx_type const octave_idx_type const double const double octave_idx_type double * V
Definition: CmplxGEPBAL.cc:49
octave_value convert_to_str_internal(bool pad, bool force, char type) const
std::string java_classname
Definition: ov-java.h:299
bool is_uint8_type(void) const
Definition: ov.h:631
string_vector map_keys(void) const
static int register_type(const std::string &, const std::string &, const octave_value &)
Definition: ov-typeinfo.cc:64
OCTINTERP_API bool Vjava_matrix_autoconversion
static int t_id
Definition: ov-java.h:313
std::string class_name(void) const
Definition: ov.h:1049
octave_value do_java_get(JNIEnv *jni_env, const std::string &name)
bool is_instance_of(const std::string &) const
bool is_undefined(void) const
Definition: ov.h:523
octave_value_list subsref(const std::string &type, const std::list< octave_value_list > &idx, int nargout)
void close(close_hook cl_hook=0)
Definition: oct-shlib.h:152
static std::string dir_sep_str(void)
Definition: file-ops.h:63
const T * fortran_vec(void) const
Definition: Array.h:481
bool is_java(void) const
Definition: ov.h:583
static octave_value do_javaObject(JNIEnv *jni_env, const std::string &name, const octave_value_list &args)
int length(void) const
Definition: dim-vector.h:281
OCTINTERP_API octave_value box_more(JNIEnv *jni_env, jobject jobj, jclass jcls=0)
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
bool is_real_matrix(void) const
Definition: ov.h:538
void F(const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n)
Definition: mx-inlines.cc:527