1. camlspotter
  2. opycaml

Commits

camlspotter  committed e15d9ba Merge

merge

  • Participants
  • Parent commits b8765f8, 419e294
  • Branches default

Comments (0)

Files changed (13)

File .hgignore

View file
 .*\.cm[a-z]+$
 .*~$
-\.(sp[io]t|annot|o|cm[a-z]+|orig|omc|lock|so|a|exe|byt)$
+\.(sp[io]t|annot|o|cm[a-z]+|orig|omc|lock|so|a|exe|byt|opt|run)$
 \.omakedb$
 ^auto\.(idl|ml|mli)
 ^.*\.idl

File IDL.txt

View file
+To add things:
+--------------
+
+- Edit <*.idl.in> files. <*.idl> are created from <*.idl.in>.
+- If you create new <*.idl.in> files, add include lines of <*.idl> in auto.idl.in, and add entries to IDLS in OMakefile.
+
+*.idl.in
+--------
+
+In addition to the CamlIDL attributes, there are some additional attributes:
+
+[option] : Pointer value may be NULL. The corresponding ML type becomes _ option.
+
+[new] : For return type only. It returns a new reference. Without this attribute, objects references are considered borrowed.
+
+[stolen] : For argument only. The function ``steals'' reference of the argument.
+
+[internal] : For function name only. ML function is prefixed with ``_internal_''
+
+Currently these new attributes are implemented by pretty dirty perl hack. They may not be used in conjunction.
+
+

File OMakefile

View file
 
 .DEFAULT: opycaml.cma opycaml.cmxa
 
-MLMODULES= test 
-CMOS=$(addsuffix .cmo, $(MLMODULES)) 
-CMXS=$(addsuffix .cmx, $(MLMODULES)) 
+OCAML_LIBS += opycaml
 
-test.byt: $(CMOS) opycaml.cma libopycaml.a dllopycaml.so
-    $(OCamlC) -verbose -o $@ opycaml.cma $(CMOS)
+.DEFAULT: $(OCamlProgram test, test)
+.DEFAULT: $(OCamlProgram test_bug1, test_bug1)
 
-test.exe: $(CMXS) opycaml.cmxa libopycaml.a dllopycaml.so
-    $(OCamlOpt) -verbose -o $@ opycaml.cmxa $(CMXS)
-
-.DEFAULT: test.exe
+# 
+# PROGRAM=test
+# FILOCAML_LIBS+=opycaml.cma
+# 
+# MLMODULES= test 
+# CMOS=$(addsuffix .cmo, $(MLMODULES)) 
+# CMXS=$(addsuffix .cmx, $(MLMODULES)) 
+# CMXOS=$(addsuffix .o, $(MLMODULES)) 
+# 
+# test.byt: $(CMOS) opycaml.cma libopycaml.a dllopycaml.so
+#     $(OCamlC) -verbose -o $@ opycaml.cma $(CMOS)
+# 
+# test.exe: $(CMXS) $(CMXOS) opycaml.cmxa libopycaml.a dllopycaml.so
+#     $(OCamlOpt) -verbose -o $@ opycaml.cmxa $(CMXS)
+# 
+# .DEFAULT: test.exe

File api.ml

View file
 	this function will not return 1, but exit the process, as long
 	as Py_InspectFlag is not set.
 
-	Bug: Py_Main never returns to OCaml at exit(_). Strange...
+	Bug: Py_Main never returns to OCaml at exit(_), while CTRL+D works fine.
     **)
 end = struct
   include Base
 
   external internal_init : unit -> unit = "opycaml_init"
   let initialize () =
-    Callback.register_exception "OPyCaml exception" (Error (none ()));
+    Callback.register_exception "OPyCaml exception" (Error (none (), none ()));
     internal_init ();
-    initialize ()
+    _internal_initialize ()
 
   let debug name o =
     let cnt = refcnt o in
 
   external reraise : unit -> 'a = "opycaml_error"
     (** reraise the current exception. 
-	Err.Occured() must be return Some. Otherwise Failwith is raised instead. *)
+	Err.Occured() must be return Some. Otherwise Failwith is
+    raised instead. *)
+
+  val normalizeException : unit -> (t * t * t) option
 end = struct
   include Err
     
   external reraise : unit -> 'a = "opycaml_error"
+
+  let normalizeException () =
+    match occurred () with
+    | None -> None
+    | Some _ -> Some (_internal_normalizeException ())
 end
 
 module Int : sig
   include Int
 
   let asLong t =
-    let res = asLong t in
+    let res = _internal_asLong t in
     if res <> -1 then res
     else match Err.occurred () with
     | None -> -1

File api_ml.c

View file
     opycaml_exc = caml_named_value("OPyCaml exception");
 }
 
-inline void opycaml_raise_error(value v)
+inline void opycaml_raise_error(value v, value detail)
 { 
-    caml_raise_with_arg(*opycaml_exc, v); 
+    value vs[2] = { v, detail };
+    caml_raise_with_args(*opycaml_exc, 2, vs); 
 }
 
 // custom value
 {
     value err;
     PyObject *exn = PyErr_Occurred(); // It's borrowed. Increment its refcnt!
+    PyObject *ptype, *pvalue, *ptraceback;
     if( !exn ){ caml_failwith("PyErr_Occurred returned NULL!"); }
     err = Val_PyObject(exn, 1); // borrowed: need to incr
-    PyErr_Print();
+    PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+    value caml_value = Val_PyObject(pvalue, 1); // incr
     PyErr_Clear();
-    opycaml_raise_error(err);
+    opycaml_raise_error(err, caml_value);
 }
 
 value Val_PyObject_opt( PyObject *obj, int incr ) {

File apitype.ml

View file
 type py_ssize_t = int
 type size_t = int
 
-exception Error of t
+exception Error of t (* type *) * t (* detail value *)
 
+

File automodular.pl

View file
 	    if( /^\s*\/\// ){ next; }
 	    if( /(Py[A-Za-z_0-9]+)\(/ ){
 		$func_name = $1;
+		if( /\[internal\]/ ){
+		    $internal{$func_name} = 1;
+		}
 		while(<IN>){
 		    if( /^\/\/\s*/ ){
 			$_ = $';
 	    $fname =~ s/py/Py/;
 	    $comment = $comment{$fname};
             $comment =~ s/\n/\n      /g;
+            $internal = $internal{$fname};
 
             # $f =~ s/GET_SIZE/get_size/;
             if( $f =~ /^[A-Z_]+$/ ){
       	        $f = lcfirst($f);
             }
     	    $f =~ s/^(type|and|or|new)$/$1_/;
+            if( $internal ){ $f = "_internal_$f"; }
     
             # rem includes type 
             $rem =~ s/pyObject_p_option/t option/g;

File base.idl.in

View file
 // --------------------------------- base
  
-void Py_Initialize();
+void [internal] Py_Initialize();
 
 void Py_Finalize();
  

File err.idl.in

View file
 boolean PyErr_GivenExceptionMatches(PyObject *given, PyObject *exc);
 // Return true if the given exception matches the exception in exc. If exc is a class object, this also returns true when given is an instance of a subclass. If exc is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match.
 
-// void PyErr_NormalizeException(PyObject**exc, PyObject**val, PyObject**tb)
+void [internal] PyErr_NormalizeException([out] PyObject**exc, [out] PyObject**val, [out] PyObject**tb);
 // Under certain circumstances, the values returned by PyErr_Fetch() below can be “unnormalized”, meaning that *exc is a class object but *val is not an instance of the same class. This function can be used to instantiate the class in that case. If the values are already normalized, nothing happens. The delayed normalization is implemented to improve performance.
 
 void PyErr_Clear();

File idlconvert.pl

View file
     s/\[option\]\s*([A-Za-z0-9_]+)/$1_option/g;
     s/\[new\]\s*([A-Za-z0-9_]+)/$1_noincr/g;
     s/\[stolen\]\s*([A-Za-z0-9_]+)/$1_incr/g;
+    s/\[internal\]//g;
     if( /^[^\/]/ ){
         s/value/value_/g;
     }

File int.idl.in

View file
 [new] PyObject* PyInt_FromSize_t(size_t ival);
 //    Create a new integer object with a value of ival. If the value exceeds LONG_MAX, a long integer object is returned.
 
-long PyInt_AsLong(PyObject *io);
+long [internal] PyInt_AsLong(PyObject *io);
 //    Will first attempt to cast the object to a PyIntObject, if it is not already one, and then return its value. If there is an error, -1 is returned, and the caller should check PyErr_Occurred() to find out whether there was an error, or whether the value just happened to be -1.
 
 // long PyInt_AS_LONG(PyObject *io);

File test.ml

View file
 open Opycaml.Api
 
+let _ = 
+  prerr_endline "start";
+  Base.initialize ()
+;;
+
 let _ =
-  prerr_endline "start";
-  Base.initialize ();
+  try
+    ignore (Import.importModule "hogehoge")
+  with
+  | Error (e, detail) ->
+      Printf.eprintf "Error: %s %s\n%!" (String.asString (Object.repr e)) (String.asString (Object.repr detail))
+;;
+
+let _ =
   let o = String.fromString "hello world" in
   Base.debug "o" o;
 
     let minus_1 = Int.fromLong (-1) in
     assert (Int.asLong minus_1 = -1); 
 
+    Run.simpleString "print 'Run.simpleString'";
+    (* Run.simpleString "print(string.lowercase)"; *) (* does not work *)
+    (* Run.simpleString "print(lowercase)"; *) (* does not work *)
+
     ignore (Base.main []);
     prerr_endline "exited from toploop";
 
-    Base.finalize ()
   with
-  | Error e -> Printf.eprintf "Error: %s\n%!" (String.asString (Object.repr e))
+  | Error (e, detail) -> 
+      Printf.eprintf "Error: %s %s\n%!" (String.asString (Object.repr e)) (String.asString (Object.repr detail))
 ;;
 
-  
+let _ = Base.finalize ()

File test_bug1.ml

View file
+open Opycaml.Api
+
+let _ = 
+  Base.initialize ();
+  ignore (Base.main []);
+  (* We cannot import things after Base.main ??? *)
+  ignore (Import.importModule "hogehoge"); 
+  Base.finalize ();
+  prerr_endline "finished"
+