Ffidl

 What: ffidl
 Where: http://elf.org/ffidl/
        http://elf.org/pub/ffidl05.zip
 Description: Extension which allows pure Tcl extensions to invoke shared
        library functions without glue.
        Available for Linux and Windows.
        Currently at version 0.5 .
 Updated: 02/2000
 Contact: mailto:rec@elf.org (Roger E. Critchlow Jr.)

Roger E Critchlow [1] has made an experimental release of ffidl, an experimental package that allows you to call C functions using pure Tcl wrappers. You specify a function name, a library, a list of argument types, and a return type, and Ffidl takes care of the nasty details of converting a Tcl command call into a C function call for you. So, if you have a shared library and a specification of the entries in the library, you can wrap the library into a Tcl extension with Ffidl and pure Tcl.

(The quotation is from the ffidl manual at [2].)

Ffidl supports calls in both directions between C/C++ and Tcl, and operates on a variety of platforms.

The name, by the way, appears to stand for "Foreign Function Interface with Dynamic Loading."


Rolf Schroedter gave a example on c.l.t on the use of ffidl

 To give you an impression about the use of ffidl,
 look at the following C and TCL-declarations:
 --- file foo.h: ---
 int foo_init( int adr, int log );
 int foo_done( void );
 int foo_info( FOO_INFO *infoPtr ); /* FOO_INFO is a structure */
 int foo_open( const char *port );
 --- file foo.tcl: ---
 load ffidl05.dll
 set DLL foo.dll
 ffidl::callout foo_init {int int} int  [ffidl::symbol $DLL foo_init]
 ffidl::callout foo_done {} int   [ffidl::symbol $DLL foo_done]
 ffidl::callout foo_info {pointer-var} int [ffidl::symbol $DLL foo_info]
 ffidl::callout foo_open {pointer-utf8} int [ffidl::symbol $DLL foo_open]

[Explain Rolf Schroedter's screensaver example in http://groups.google.com/groups?th=ec295f4a4849b362 .]

 #Rolf Schroedter
 #German Aerospace Center
 #Institute of Space Sensor Technology and Planetary Exploration

 load ffidl05.dll

 ffidl::callout dll_FindWindow       {pointer-utf8 pointer-utf8} int     [ffidl::symbol user32.dll FindWindowA]
 ffidl::callout dll_FindWindowTitle  {int pointer-utf8} int              [ffidl::symbol user32.dll FindWindowA]
 ffidl::callout dll_FindWindowClass  {pointer-utf8 int} int              [ffidl::symbol user32.dll FindWindowA]
 ffidl::callout dll_SetWindowPos     {int int int int int int int} int   [ffidl::symbol user32.dll SetWindowPos]
 ffidl::callout dll_SystemParametersInfo {int int pointer int} int       [ffidl::symbol user32.dll SystemParametersInfoA]

 proc FindWindow { class title } {
    if { [string length $class] == 0 } {
        dll_FindWindowTitle 0 $title
    } elseif { [string length $title] == 0 } {
        dll_FindWindowClass $class 0
    } else {
        dll_FindWindow $class $title
    }
 }
 proc SetWindowPos { hwnd after x y cx cy {flags 0} } {
    array set VAL {TOP 0 BOTTOM 1 TOPMOST -1 NOTOPMOST -2}
    set iAfter $VAL([string toupper $after])
    dll_SetWindowPos $hwnd $iAfter $x $y $cx $cy $flags
 }
 proc SetupScreenSaver { bool } {
    dll_SystemParametersInfo 97 $bool 0 0   ;# SPI_SCREENSAVERRUNNING=97
 }
 proc exit? {} {
    set answer [tk_messageBox -message "Really quit?" -type yesno -icon question]
    switch -- $answer {
        yes {
            SetupScreenSaver 0
            exit
        }
        no {}
    }
 }
 proc ScreenSaver {win} {
    set size(X) [winfo screenwidth .]
    set size(Y) [winfo screenheight .]

    toplevel $win
    wm title $win "TclScreenSaver"     ;# to find the window

    wm overrideredirect $win true
    $win configure -relief flat -bd 0
    $win configure -cursor hand2    ;# Ohne cursor ???

    update idletasks                ;# virtually display $win, allows window to be found
    set hwnd [FindWindow "" "TclScreenSaver"]
    set res1 [SetWindowPos $hwnd TOPMOST 0 0 $size(X) $size(Y)]   ;# ever makes full screen
    set res2 [SetupScreenSaver 1]

    canvas $win.c -background yellow -width $size(X) -height $size(Y) -relief flat -bd 0
    pack $win.c -expand yes -fill both

    focus -force $win

    bind $win <Key> exit?
    bind $win <Motion> {}
 }

 wm withdraw .
 ScreenSaver .scr

Per: [Rob Hegt] post on c.l.t Subject: solution for regaining focus from OpTcl hosted ActiveX control

 load lib/ffidl05.dll
 ffidl::callout dll_SetFocus {int} int [ffidl::symbol user32.dll SetFocus]
 proc GrabFocus {args} {dll_SetFocus [winfo id .]}

Then just bind GrabFocus to some event. In the post he uses <button> .

 bind . <Button> +GrabFocus

Michael Jacobson ~ Also see always on top for a another example.


Michael Jacobson ~ AutoIt wrapper code using Ffidl is here [3].


ZLM ~ web2desktop includes an example of using ffidl to set the Windows desktop background.


An energetic person could use SWIG to wrap all the standard Win32api to make it accessible in a more-or-less standard way for Tcl. No one yet seems motivated to do this.


critcl provides an alternative way approach for "calling functions in arbitrary dynamic libraries" [4].