<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE TIP SYSTEM "http://www.tcl.tk/cgi-bin/tct/tip/tipxml.dtd">
<!-- Converted at Sun Feb 12 12:09:17 GMT 2012 -->
<!-- TIP AutoGenerator - written by Donal K. Fellows -->

<TIP number='357'>
<header><title>Export TclLoadFile</title><author address="mailto:kevin.b.kenny@gmail.com">Kevin Kenny</author><status type='project' state='final' tclversion="8.6" vote='after'>$Revision: 1.14 $</status><history></history><created day='1' month='oct' year='2009' /></header>
<abstract>This TIP proposes to promote the internal calls, <emph style="italic">TclLoadFile</emph> and <emph style="italic">TclpFindSymbol</emph> to the external API, making them available to C extensions. In addition, it proposes to introduce a <emph style="italic">Tcl_FSUnloadFile</emph> to the VFS layer, removing the weird duplicate client data from <emph style="italic">TclLoadFile</emph> and wrapping all necessary data into the <emph style="bold">Tcl_LoadHandle</emph></abstract>
<body><section title="Rationale">
<para>In developing TDBC <tipref type="text" tip="308"/>, the author of this TIP was advised to look at the way that the &apos;oratcl&apos; extension contrives to build on a system where Oracle is not installed as a model for TDBC extensions. Examination of the code revealed that it operates essentially by constructing at run time a Stubs table for the routines in the Oracle client library. There is a maze of <emph style="bold">#if</emph> directives selecting whether this process is accomplished by the system calls that manage Unix .so files (<emph style="italic">dlopen</emph> and friends), Windows .DLL files (<emph style="italic">LoadLibrary</emph> and related calls), HP-UX .shl files (<emph style="italic">shl_load,</emph> etc.), and so on.</para>
<para>Tcl already has functionality so that a caller can abstract away all this complexity. It provides the capability in the <emph style="italic">TclLoadFile</emph> call, but this call is <emph style="bold">MODULE_SCOPE</emph> and not exported even in the internal Stubs table. For this reason, it is entirely unavailable to TEA-compliant extensions.</para>
<para>If this call were available, it would be feasible, in the 8.6 time frame, to bundle all the database-specific TDBC drivers with the core TDBC distribution, since things could be set up so that they will build anywhere, even in the absence of the databases where they connect.</para>
<para>However, this call was never fully rationalized in the VFS world. Its strange API (with both a <emph style="bold">Tcl_LoadHandle</emph> and a <emph style="bold">ClientData</emph>, and a function pointer for unloading the library) is, as several reviewers pointed out, not somehting that we want to make available to general callers. Hence, a few more routines need rework.</para>
</section>
<section title="Specification">
<para>The <emph style="italic">TclLoadFile</emph> call shall be renamed <emph style="italic">Tcl_LoadFile</emph> and exported in the external Stubs. Its call signature shall be changed to:</para>
<quote>EXTERN int <emph style="bold">Tcl_LoadFile</emph>( Tcl_Interp *<emph style="italic">interp</emph>, Tcl_Obj *<emph style="italic">pathPtr</emph>, const char *<emph style="italic">symbols</emph>[], int <emph style="italic">flags</emph>, void *<emph style="italic">procPtrs</emph>, Tcl_LoadHandle *<emph style="italic">handlePtr</emph>);</quote>
<para>In this call, <emph style="italic">interp</emph> designates an interpreter for error reporting. <emph style="italic">pathPtr</emph> is an object containing the path of the library to be loaded. If <emph style="italic">pathPtr</emph> is a single name, the library search path of the current environment will be used to resolve it. The <emph style="italic">symbols</emph> array contains a NULL-terminated set of character strings that are the names of the imported symbols. <emph style="italic">symbols</emph> may be NULL if the library is to be loaded without resolving any symbols.</para>
<para>The return value of <emph style="italic">Tcl_LoadFile</emph> is a standard Tcl result code. If the result is TCL_ERROR, the interpreter result will contain an appropriate error message.</para>
<para>On return, <emph style="italic">Tcl_LoadFile</emph> fills in the block of memory commencing at the address given by <emph style="italic">procPtrs</emph> with the addresses that correspond to the names in <emph style="italic">symbols.</emph> If a name cannot be resolved in the given library, an error will be returned and all entries in <emph style="italic">procPtrs</emph> will be invalid. <emph style="italic">procPtrs</emph> may be NULL if no symbols are to be resolved.</para>
<para>On a successful return, the <emph style="italic">loadHandle</emph> pointer will be a handle suitable for passing to <emph style="italic">Tcl_FindSymbol</emph> for resolving additional symbols in the library, or to <emph style="italic">Tcl_FSUnloadFile</emph> to unload the library.</para>
<para>The <emph style="italic">TclpFindSymbol</emph> call shall be renamed <emph style="italic">Tcl_FindSymbol</emph> and exported in the external Stubs. Its call signature shall be:</para>
<quote>EXTERN void* <emph style="bold">Tcl_FindSymbol</emph>( Tcl_Interp *<emph style="italic">interp</emph>, Tcl_LoadHandle *<emph style="italic">loadHandle</emph>, const char *<emph style="italic">symbol</emph>);</quote>
<para>This call searches for the given <emph style="italic">symbol</emph> in the already-loaded library identified by <emph style="italic">loadHandle</emph>. If the symbol is found, a pointer to its memory address is returned. Otherwise, NULL is returned, and an error message is left in <emph style="italic">interp</emph> (if <emph style="italic">interp</emph> is not NULL).</para>
<para>A new call, <emph style="italic">Tcl_FSUnloadFile</emph> shall be introduced and exported in the external Stubs.Its call signature shall be:</para>
<quote>EXTERN int <emph style="bold">Tcl_FSUnloadFile</emph>( Tcl_Interp *<emph style="italic">interp</emph>, Tcl_LoadHandle *<emph style="italic">loadHandle</emph>);</quote>
<para>This call unloads the library identified by <emph style="italic">loadHandle</emph>. It differs from the [unload] command in that no &apos;unload&apos; procedure is called; the library is simply unloaded without first being given a chance to clean itself up. (This function is a lower-level interface used by [unload] as part of doing its work.) The return value is either TCL_OK or TCL_ERROR; when TCL_ERROR is returned, an appropriate message is left in the result of <emph style="italic">interp</emph> (if <emph style="italic">interp</emph> is not NULL).</para>
</section>
<section title="Internals">
<para>The <emph style="bold">Tcl_LoadHandle</emph> object shall be represented internally by a structure, declared in &lt;tclInt.h&gt;, looking like:</para>
<verbatim><vline encoding='base64'>IHN0cnVjdCBUY2xfTG9hZEhhbmRsZV8gew==</vline><vline encoding='base64'>ICAgICBDbGllbnREYXRhIGNsaWVudERhdGE7CS8qIENsaWVudCBkYXRhIGlzIHRoZSBsb2FkIGhhbmRsZSBpbiB0aGU=</vline><vline encoding='base64'>IAkJCQkgKiBuYXRpdmUgZmlsZXN5c3RlbSBpZiBhIG1vZHVsZSB3YXMgbG9hZGVk</vline><vline encoding='base64'>IAkJCQkgKiB0aGVyZSwgb3IgYW4gb3BhcXVlIHBvaW50ZXIgdG8gYSBzdHJ1Y3R1cmU=</vline><vline encoding='base64'>IAkJCQkgKiBmb3IgZnVydGhlciBib29ra2VlcGluZyBvbiBsb2FkLWZyb20tVkZT</vline><vline encoding='base64'>IAkJCQkgKiBhbmQgbG9hZC1mcm9tLW1lbW9yeSAqLw==</vline><vline encoding='base64'>ICAgICBUY2xGaW5kU3ltYm9sUHJvYyogZmluZFN5bWJvbFByb2NQdHI7</vline><vline encoding='base64'>IAkJCQkvKiBQcm9jZWR1cmUgdGhhdCByZXNvbHZlcyBzeW1ib2xzIGluIGE=</vline><vline encoding='base64'>IAkJCQkgKiBsb2FkZWQgbW9kdWxlICov</vline><vline encoding='base64'>ICAgICBUY2xfRlNVbmxvYWRGaWxlUHJvYyogdW5sb2FkRmlsZVByb2NQdHI7</vline><vline encoding='base64'>IAkJCQkvKiBQcm9jZWR1cmUgdGhhdCB1bmxvYWRzIGEgbG9hZGVkIG1vZHVsZSAqLw==</vline><vline encoding='base64'>IH0=</vline></verbatim>
<para>The <emph style="italic">Tcl_FindSymbolProc</emph> and <emph style="italic">Tcl_FSUnloadFileProc</emph> data types are declared to be functions of the same type signature as <emph style="italic">Tcl_FindSymbol</emph> and <emph style="italic">Tcl_FSUnloadFile</emph>.</para>
<para>Virtual file systems that implement the <emph style="italic">loadFileProc</emph> are responsible for ensuring that their <emph style="italic">&apos;Tcl_LoadHandle</emph> that the <emph style="italic">loadFileProc</emph> returns conforms with this convention. As far as the author has been able to determine, no non-Core filesystem provides anything but NULL for the <emph style="italic">loadFileProc</emph>. Certainly, tclvfs and trofs do not. Most other virtual filesystems layer atop tclvfs. </para>
</section>
<section title="Reference Implementation">
<para>A reference implementation is nearing completion, and the draft code is available attached to [Patch 2891616][<url ref="https://sourceforge.net/support/tracker.php?aid=2891616"/>] at SourceForge.</para>
</section>
<section title="License">
<para>This file is explicitly released to the public domain and the author explicitly disclaims all rights under copyright law.</para>
</section>
</body></TIP>

