caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Using Tk extensions under caml/labltk
@ 2000-03-22 20:21 Michael Hohn
  2000-03-24  8:10 ` Jacques Garrigue
  0 siblings, 1 reply; 3+ messages in thread
From: Michael Hohn @ 2000-03-22 20:21 UTC (permalink / raw)
  To: caml-list


Recently, I needed to use the BLT extension to Tk.  Since all my data comes
from ocaml, and there is a fair amount of data, I wrote a simple C interface.
Below are the steps I took under ocaml-2.04.
My questions are:

1.  Why is tcl_eval not exported by default (in protocol.mli)?  I
    don't like Tcl much, but 
    for trivial commands like "package require blt", I don't see a
    problem with direct string evaluation.
    Also, it would be nice to have some interactive control over caml programs
    compiled to native code; wouldn't Tcl work well for this?

2.  Apparently, most high-level widget interfaces are defined in
    otherlibs/labltk/Widgets.src, with special routines in 
    otherlibs/labltk/builtin/* and general low level support in 
    otherlibs/labltk/support.
    Since I only needed a small subset of the BLT commands and
    couldn't quite figure out the details in this setup, I used direct
    string evaluation with some embedded caml callbacks, e.g.

    tcl (g.g_name ^ " element create line_" ^ xv ^ " \
	     -xdata "^ xv ^ " -ydata "^ yv ^ " \
	     -symbol {} \
	     -pixels 0.1c \
	     -color "^
	     (domain_color dom) ^ "\n")

    Needless to say, a clean wrapper would be better.	   

    Is there a particular approach to be followed when adding new
    widgets?

    Or better yet, does someone have a *documented* example for the
    addition of a widget requiring additions in all three places :) ?


Cheers,
	Michael



Here are my notes:
    To really use Tcl with camltk requires some special
    installation steps. 
    
    1.  Produce the include file camltk41/camltk.h
	This include file must be manually installed from the
	ocamltk41 distribution; e.g.
	    cp ocamltk41/support/camltk.h /usr/local/lib/ocaml/camltk41
    
    2.  The caml header file protocol.mli is ....  It does not
	provide the (very useful) function tcl_eval.
    
	To fix this, do:
	    cd ./otherlibs/labltk/support
	    [ cd ocamltk41/support in 2.04 ]
	    cat >>  protocol.mli <<EOF
    val tcl_eval : string -> string
    EOF
	BEFORE compiling the ocamltk41.
	[Doing this after and re-installing only changed files causes
	    inexplicable core dumps later.]
    
	[Compare:
	     tcl_eval "package require BLT"
	 vs. 
	     tkEval [| TkToken "package"; TkToken "require"; TkToken "BLT"
	     |];;
	 On longer inputs, this would not be amusing... ]
	
Using these, the following worked:
grid_ocaml.ml:
    (*
       set_blt_vector name array --
	   set/create the BLT array "name" and
	   set its entries to the values in <array>.
    *)
    external set_blt_vector : string -> float array -> unit = "set_blt_vector_" 
	
And the C file:
    
    #include <tcl.h>
    #include <blt.h>
    
    #include "caml/mlvalues.h"
    /* 
       This include file must have been manually installed from the
       ocamltk41 distribution; e.g.
       cp ocamltk41/support/camltk.h /usr/local/lib/ocaml/camltk41
    
       Some code taken from the ocaml/fortran interface example.
    
    */
    #include "camltk41/camltk.h"
    
    
    value set_blt_vector_(value vName, value vA)
    {
	char *name  = String_val(vName);
    
	/*
	 * Do we have a native, ocamlopt array or a bytecode, ocamlc one?
	 */
    
	int isNative = Tag_val(vA) == Double_array_tag;
    
	/*
	 * How big is it?
	 */
    
	int arrayLength =
	isNative ? Bosize_val(vA) / sizeof(double) : Wosize_val(vA);
    
	Blt_Vector *vecPtr;
	double *newArr;
    
	/* 
	 * Make sure the Tcl interpreter exists.
	 */
	if (cltclinterp == NULL) 
	failwith("Tcl not initialized.");
    
	/*
	 * Make [newArr] point to a C-friendly version of [vA]
	 */
    
	/* Allocate the array on the C heap, and let BLT free() it (see
	   below). */
	newArr = (double *)malloc(arrayLength * sizeof(double));
    
	if (isNative)
	{
	    /* ocamlopt-style array: copy it using [Double_field] */
		int i;
		    for (i = 0; i < arrayLength; ++i)
			newArr[i] = Double_field(vA, i);
			}
	else
	{
	    /* ocamlc-style array: copy it using [Double_val(Field(...))]
	*/
	    int i;
		for (i = 0; i < arrayLength; ++i)
		    newArr[i] = Double_val(Field(vA, i));
		    }
    
    
	/*
	 * Prepare the BLT vector. 
	 */
	if (Blt_VectorExists(cltclinterp, name))  {
	if (Blt_GetVector(cltclinterp, name, &vecPtr) != TCL_OK) 
	    failwith("Tcl error.");
	} else {
	if (Blt_CreateVector(cltclinterp, name, 0, &vecPtr) != TCL_OK) 
	    failwith("Tcl error.");
	}
	/*
	 * Reset the vector to use the new array. Clients will be notified
	 * when Tk is idle. 
	 * TCL_DYNAMIC tells the vector to free the memory allocated
	 * if it needs to reallocate or destroy the vector.
	 */
	if (Blt_ResetVector(vecPtr, newArr, arrayLength, arrayLength,
				    TCL_DYNAMIC) != TCL_OK)
				    failwith("Tcl error.");
      
	return Val_unit;
    }
	



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Using Tk extensions under caml/labltk
  2000-03-22 20:21 Using Tk extensions under caml/labltk Michael Hohn
@ 2000-03-24  8:10 ` Jacques Garrigue
  2000-03-24 18:09   ` Michael Hohn
  0 siblings, 1 reply; 3+ messages in thread
From: Jacques Garrigue @ 2000-03-24  8:10 UTC (permalink / raw)
  To: hohn; +Cc: caml-list

From: Michael Hohn <hohn@math.utah.edu>

> Recently, I needed to use the BLT extension to Tk.  Since all my data comes
> from ocaml, and there is a fair amount of data, I wrote a simple C interface.
> Below are the steps I took under ocaml-2.04.
> My questions are:
> 
> 1.  Why is tcl_eval not exported by default (in protocol.mli)?  I
>     don't like Tcl much, but 
>     for trivial commands like "package require blt", I don't see a
>     problem with direct string evaluation.

You can do something equivalent by using the Protocol.tkEval command.
You just have to preparse your string. This is basically how the whole
library is built.
  val tkEval : tkArgs array -> string

>     Also, it would be nice to have some interactive control over
>     caml programs compiled to native code; wouldn't Tcl work well
>     for this?

Doesn't sound like a very good idea to me.
I don't know what are your exact needs, but you might have a look at
what is done inside efuns
 http://pauillac.inria.fr/para/cdrom/prog/unix/efuns/eng.htm
There Fabrice Le Feissant has a bytecode interpreter written in Caml,
allowing dynamic loading of caml bytecode inside a native application.
This is reasonably efficient. 

> 2.  Apparently, most high-level widget interfaces are defined in
>     otherlibs/labltk/Widgets.src, with special routines in 
>     otherlibs/labltk/builtin/* and general low level support in 
>     otherlibs/labltk/support.

This approach also allows to define interfaces for other libraries
independently. I don't know very well how this works, so somedbody more
competent should answer, but for instance there was already an
interface for BLT in the camltk41 version distributed with MMM.

Jacques
---------------------------------------------------------------------------
Jacques Garrigue      Kyoto University     garrigue at kurims.kyoto-u.ac.jp
		<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Using Tk extensions under caml/labltk
  2000-03-24  8:10 ` Jacques Garrigue
@ 2000-03-24 18:09   ` Michael Hohn
  0 siblings, 0 replies; 3+ messages in thread
From: Michael Hohn @ 2000-03-24 18:09 UTC (permalink / raw)
  To: garrigue; +Cc: caml-list


>From <garrigue@kurims.kyoto-u.ac.jp>:

>> ...
>>    You can do something equivalent by using the Protocol.tkEval command.
>>    You just have to preparse your string. This is basically how the whole
>>    library is built.
>>      val tkEval : tkArgs array -> string
>> ...

True.  Buried in my message was this:
	[Compare:
	     tcl_eval "package require BLT"
	 vs. 
	     tkEval [| TkToken "package"; TkToken "require"; TkToken "BLT"
	     |];;
	 On longer inputs, this would not be amusing... ]

This could be cleaned up by using Str.split, but that means a lot of
wasteful computing.
	

>> ...
>> 
>>    >     Also, it would be nice to have some interactive control over
>>    >     caml programs compiled to native code; wouldn't Tcl work well
>>    >     for this?
>> 
>>    Doesn't sound like a very good idea to me.
>> ...


There are several advantages to embedding caml in Tcl and using
(simple) Tcl scripts:

1.  All existing Tcl documentation can be used unchanged.  This is a
    problem in all languages that use their own bindings to Tcl.  Just
    recently, I had to battle with Python's binding methodology.
    Fortunately, a partial BLT wrapper was available.

2.  All Tk extensions will work immediately.  No need to produce
    wrapper function after wrapper function.  Again, Python's tkinter
    is a good example of pain...

3.  Conversion to and from Tcl takes time.  After profiling my
    Python/Tkinter GUI, about 25% (yes, 25%) of the time went to the
    argument conversion routines!  This would be better in caml, but
    it's bad in any event. 


>> ...
>> 
>>      I don't know what are your exact needs, but you might have a look at
>>      what is done inside efuns
>>       http://pauillac.inria.fr/para/cdrom/prog/unix/efuns/eng.htm
>>      There Fabrice Le Feissant has a bytecode interpreter written in Caml,
>>      allowing dynamic loading of caml bytecode inside a native application.
>>      This is reasonably efficient. 
>> ...

And uses caml, which is what I want.  The problem thus reduces to
producing caml bindings, my second question:


>> ...
>>    > 2.  Apparently, most high-level widget interfaces are defined in
>>    >     otherlibs/labltk/Widgets.src, with special routines in 
>>    >     otherlibs/labltk/builtin/* and general low level support in 
>>    >     otherlibs/labltk/support.
>> 
>>    This approach also allows to define interfaces for other libraries
>>    independently. I don't know very well how this works, so somedbody more
>>    competent should answer, but for instance there was already an
>>    interface for BLT in the camltk41 version distributed with MMM.
>> ...

Yes, there was.  But again, there is no documentation of the idea
behind the binding.  After fiddling with it for a few hours, I dropped
it.  If I remember correctly, the binding was for version 1.8 of BLT,
and did not include the graph widget :(

Thanks for the ideas.  I'll have another look at MMM...

Cheers,
	Michael



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2000-03-27 17:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-03-22 20:21 Using Tk extensions under caml/labltk Michael Hohn
2000-03-24  8:10 ` Jacques Garrigue
2000-03-24 18:09   ` Michael Hohn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).