TIP: | 60 |
Title: | EXTERN Macro Change to Support a Wider Set of Attributes |
Version: | $Revision: 1.21 $ |
Authors: |
David Gravereaux <davygrvy at pobox dot com> Donal K. Fellows <fellowsd at cs dot man dot ac dot uk> |
State: | Rejected |
Type: | Project |
Tcl-Version: | 8.6 |
Vote: | Done |
Created: | Thursday, 06 September 2001 |
This TIP proposes a change to how the EXTERN macro in tcl.h works to support a wider range of compiler specific attributes.
With working on Borland support recently, I found that luckily the newest "free commandline tools" [1] does support Microsoft's __declspec(dllexport) attribute. But at the same time, the older way with __export is still valid, but can't be used due to the order within the prototype declaration of the EXTERN macro.
What's this with the MS compiler:
__declspec(dllexport) __cdecl int func (int a, int b);
will have to be this with Borland:
int __export __cdecl func (int a, int b);
The order of the attribute needs to be after the return type.
Even though __declspec is supported in the Microsoft style with version 5.5+ of the Borland compiler, if EXTERN could swap around the order a hair, old Turbo C v5.0 has a better chance to make a DOS library. Should someone feel the need.
Let's leave the existing EXTERN macro as-is and just make a new one called TCL_EXTERN to support the new behavior.
Karl Lembuaer (sp?) did a presentation @ OSCON regarding his recent tinytcl project %TODO: add link here% about his DOS port of Tcl 6.7 for use in a hand-held device.
Stepping backward for DOS support, may actually be a leap forward in an off-beat manner...
I saw something like this in a very old DDE extension that someone at Sun wrote. It was used as an example windows extension for years.
ftp://tcl.activestate.com/pub/tcl/misc/example.zip
In example.h is this:
#if defined(__WIN32__) # if defined(_MSC_VER) # define EXPORT(a,b) __declspec(dllexport) a b # else # if defined(__BORLANDC__) # define EXPORT(a,b) a _export b # else # define EXPORT(a,b) a b # endif # endif #else # define EXPORT(a,b) a b #endif EXTERN EXPORT(int,Example_Init) _ANSI_ARGS_((Tcl_Interp *interp));
That work is doing the same job, but I prefer the method that I'm proposing.
It is also mentioned on http://tcl.activestate.com/doc/howto/winext.html and feel it is rather out-of-date and the order issue with __export should be brought into the core with this patch and be fix for good.
Is>
EXTERN int Foobar_Init (Tcl_Interp *interp);
Proposed>
TCL_EXTERN(int) Foobar_Init (Tcl_Interp *interp);
https://sourceforge.net/tracker/download.php?group_id=10894&atid=310894&file_id=70480&aid=436116
Is:
EXTERN int Foobar_Init (Tcl_Interp *interp) { #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } #endif Tcl_CreateObjCommand(interp, "foobar", FooBar, NULL, NULL); return TCL_OK; };
Proposed:
TCL_EXTERN(int) Foobar_Init (Tcl_Interp *interp) { #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } #endif Tcl_CreateObjCommand(interp, "foobar", FooBar, NULL, NULL); return TCL_OK; };
Preprocessor output is the following:
Borland:
/* foobar.c 14: */extern int __export /* foobar.c 15: */Foobar_Init (Tcl_Interp *interp) /* foobar.c 16: */{ /* foobar.c 17: */ /* foobar.c 18: */if (Tcl_InitStubs(interp, "8.1", 0) == 0) { /* foobar.c 19: */return 1; /* foobar.c 20: */} /* foobar.c 21: */ /* foobar.c 22: */(tclStubsPtr->tcl_CreateObjCommand)(interp, "foobar", FooBar, 0, 0); /* foobar.c 23: */return 0; /* foobar.c 24: */};
VC++:
extern __declspec(dllexport) int Foobar_Init (Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.1", 0) == ((void *)0)) { return 1; } #line 22 "foobar.c" (tclStubsPtr->tcl_CreateObjCommand)(interp, "foobar", FooBar, ((void *)0), ((void *)0)); return 0; };
MinGW (native gcc on win):
extern int Foobar_Init (Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.1", 0) == ((void *)0) ) { return 1 ; } (tclStubsPtr->tcl_CreateObjCommand) (interp, "foobar", FooBar, ((void *)0) , ((void *)0) ); return 0 ; };
In tclInt.h starting around line 1916, are prototypes for the internal cmdprocs. I can't think of any reason why they should be exported. Also note the comment about line:1673, as it states:
/* *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside * world: *---------------------------------------------------------------- */
As the current EXTERN macro places ""everything"" exportable, the use of EXTERN following this comment in tclInt.h is contradictory. In place of EXTERN for this purpose I used the new TCL_EXTRNC in the reference implementation.
This document has been placed in the public domain.
[Index] [History] [HTML Format] [Source Format] [LaTeX Format] [Text Format] [XML Format] [*roff Format (experimental)] [RTF Format (experimental)]
TIP AutoGenerator - written by Donal K. Fellows