Another package called Ffidl has been developed by Roger E. Critchlow Jr and as this package supports more platforms and is arguably better structured, ::dll should now be considered deprecated.
Tthe first form attempts to call procedure name in
DLL path with argument list defined by argdefs
and return value defined by returndef.
In the second form @addr is taken as an address and offs is added to form the address of the function to call.
In the third form @@vec is taken as the address of a vector
of function pointers and index is taken as the element of
this vector to use as the address of the function to call.
Returndef | Argdef | |||
---|---|---|---|---|
v | No return value | {*n var}
{*sn var} |
Pointer to a tcl variable named var. If var doesn't exist it will be created and assigned a string of length n. Eg {*256 buffer}. If n is omitted the variable must exist; otherwise it will be created to have the specified length in bytes. If the integer is preceded by s then the created variable will be truncated to the first zero byte. | |
i |
|
{i intvalue} | The argument is a 4byte value. Eg {i 2021} | |
|
|
{f floatvalue} | The argument is a double value which is passed as a float. | |
|
|
{d doublevalue} | The argument is a double value. Eg {d 4.7} | |
|
|
{b string} | A string value. The binary command can be used to create this. Eg {b {this is a string}}. The whole string is passed as a value. | |
{s string} | A constant string to be passed by address. Example {s {c:\windows\media\chord.wav} | |||
{n string} | An n byte binary value. Differs from argtype b in that the length is fixed. Example {7 S123456} | |||
{@ Callback} | A predefined callback At present only synchronous callbacks are supported. |
The cdecl and stdcall subcommands create
callback routines which may be used with the @ argument descriptor for
the ::dll::call command. The cbname argument is the internal
name by which the callback is known. The tclname argument
is the name of a tcl proc which will effectively be substituted for the
callback routine. The delete and info subcommands
delete or return information about callbacks whose internal names match
a pattern.
Callback Returndef | Callback Argdef | |||
---|---|---|---|---|
v | No return value | Not allowed | ||
i |
|
The argument is a 4byte value. It will be passed as an int Tcl_Object | ||
|
|
The argument is a float value which is passed as a double Tcl_Object.. | ||
|
|
The argument is a double value which is passed as a double Tcl_Object.. | ||
|
|
A binary string value. It will be passed to the tcl proc as a string of the right length (I hope). The binary command can be used to interpret this. | ||
s | A constant string address. At present this is like the i return as I'm unsure how to create persistent string values which can be reclaimed. | A constant null terminated string to be passed by address. This will be passed to the tcl proc as a string object. |
::dll::declare path routine tclprocname returndefargdefs...This command predeclares a TCL proc named tclprocname as an interface to routine in dll path. Tthe returndef and argdefs are similar to those for the command ::dll::call above, but if no value is supplied for an argdef (ie only a type is supplied) then the argument is made into a free argument of the created proc and must be supplied when the proc is called. Declared procsare in general more efficient when called than using ::dll::call. As an example on my machine (333Mhz Pentium Pro). The second and third forms supply the function address similarly to ::dll::call.
::dll::declare @addr offs tclprocname returndefargdefs...
::dll::declare @@vec index tclprocname returndefargdefs...
proc CFunc_i {i j} {return [::dll::call ./objs/testdll.dll func_i i [list i $i] [list i $j]]}Supplied values are pre-evaluated at declare time; this means that constant callbacks must exist at declare and use time at present deleting such a callback would cause problems.
::dll::declare ./objs/testdll.dll func_i DFunc_i i i i
time {CFunc_i 1 2} 1000000 --> 40 microseconds
time {DFunc_i 1 2} 1000000 --> 3 microseconds
::dll::get_interpGets the address of the calling interpreter as an integer; this is a special hack to allow us to pass an Tcl_Interp pointer to routines in tcl80 etc.
::dll::setoffs integer [s|i|d|f|<integer>][:<integer>]+ [value]Sets or gets an indirect value from a known address integer.The indirection (second) argument has the form typecode[:offset]+ ie a typeletter which can be one of i, d, f, s or an integer meaning the pointed at final value is an integer, double, float, null terminated string or nbyte value followed by one or more : offset pairs. For each : (colon) except the first an indirection through the pointer is performed and the following integer is added as a byte offset. In the two argument form the the pointed at value is the result, in the three argument form the third argument is copied to the address determined by the pointer and the original value is returned.
::dll::int2str integerSome APIs pass either pointers to strings or integers with runtime tests being used to determine whether the actual passed value is a string or a meaningful integer. If an integer is known to be a string pointer this function can be used to obtain the string.
::dll::dinfo patternReturns information about declared aliases which match pattern.
#Function GetWindowsDirectoryA Lib "KERNEL32" #(ByVal lpbuffer As String, ByVal nsize As Integer) As Long load dll02 set i [::dll::call kernel32 GetWindowsDirectoryA i {*256 buffer} {i 255}] puts "$i [string range $buffer 0 10]"
#Around 8680 microseconds/call proc EnumWindows {} { proc EnumWCB {i s} { upvar 1 $s L lappend L 0x[format %x $i] return 1 } ::dll::callback cdecl EnumWCB EnumWCB i i s set WindowList {} ::dll::call user32.dll EnumWindows i {@ EnumWCB} {s WindowList} rename EnumWCB {} ::dll::callback delete EnumWCB return $WindowList } puts "[EnumWindows]"On my Win95 system this produces '10 C:\WINDOWS' and a list of hex toplevel window numbers. Other examples are in the files example.tcl and demo.tcl.
#The above could also be coded at around 8350 microseconds per iteration proc EnumWCB {i s} { upvar 1 $s L lappend L 0x[format %x $i] return 1 } ::dll::callback cdecl EnumWCB EnumWCB i i s ::dll::declare user32.dll EnumWindows _EnumWindows i {@ EnumWCB} {s WindowList} proc EnumWindows {} { set WindowList {} _EnumWindows return $WindowList }