* 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