Dirk: Well I finally took your advice and speed tested a left() in C
vs Rettig's Clipper coded left(). My version looks like:
.
#include <extend.h>
int strlen();   /* use Clipper fcn for strlen */
void left() {
   char *str;
   unsigned int cnt;
   if (PCOUNT == 2 && ISCHAR(1) && ISNUM(2)) {
      str = _parc(1); cnt = _parni(2);
      if (cnt < strlen(str))
         str[cnt] = '\0';
      _retc(str);
   }
   else
      _retc("Error...");
}
Note that I have included full parameter error checking. It is my
firm belief that ASM and C UDFs MUST HAVE PARAMETER ERROR CHECKING,
else one can have weird and unpredictable results, lockups, etc!!
.
The timing for 10000 FOR/NEXT loops for short and long strings, in
seconds is: (empty loop time was 30 sec) (10MHz AT)
             internal   left()       Clipper Code left()
             substr()  C-version    Rettig    Rettig(with error checking)
strlen=10       56        62          87        139       
strlen=1000     68        91         113        165
.
The use of parameter checking in the Rettig Clipper coded left() is
probably not needed since at run time you will get "Q/A/I" errors if
you screwup the parameters, but note the high penalty. This was all
done in A'86 with Lattice ver 3. 
.
I conclude that the C code is 87-30/62-30=1.8X faster than the best
Clipper coded left() and there is some decrease in this speed ratio
for long strings. It even compares surprisingly well with the Clipper
internal substr() function. The whole test source code and file
LEFT.OBJ is uploaded in the file LEFTSPED.ARC.
.
Oh, I don't think the extended interface is all that bad. As you can 
see from the above, just adding the error checking in Clipper coded
left() added a delta 52 sec, almost as much extra as total C version
time required, including the looping time! According to the LIB
listing for A'86, the extend module is only a total of 444H code+data
a whole lot less than the 4-8K you mentioned in your msg to me.
.
Enjoy, Harry

**    Last revision: January 21, 1988  
*
*  Program LEFTSPED.PRG to test C and Clipper coded left() routines.
*  LINK LEFTSPED+LEFT; note LEFT.OBJ is included in this ARC file.
*  for: A'86 version by: H.M. Van Tassell
*

? time()
? "doing empty loop"
FOR I=1 TO 10000
 * empty loop  
NEXT
mvar = SPACE(10)
? time()
? "doing 10,000 left(strlen=10)"
FOR I=1 TO 10000
  x = left(mvar,5)
NEXT
? time()
? "doing 10,000 left_tr(strlen=10)"
FOR I=1 TO 10000
  x = left_tr(mvar,5)
NEXT
? time()
? "doing 10,000 left_vt(strlen=10)"
FOR I=1 TO 10000
  x = left_vt(mvar,5)
NEXT
? time()
? "doing 10,000 substr(strlen=10)"
FOR I=1 TO 10000
  x = substr(mvar,1,5)
NEXT
*
mvar = SPACE(1000)
? time()
? "doing 10,000 left(strlen=1000)"
FOR I=1 TO 10000
  x = left(mvar,5)
NEXT
? time()
? "doing 10,000 left_tr(strlen=1000)"
FOR I=1 TO 10000
  x = left_tr(mvar,5)
NEXT
? time()
? "doing 10,000 left_vt(strlen=1000)"
FOR I=1 TO 10000
  x = left_vt(mvar,5)
NEXT
? time()
? "doing 10,000 substr(strlen=1000)"
FOR I=1 TO 10000
  x = substr(mvar,1,5)
NEXT
? time()
*
WAIT
*
mvar = "1234567890"
? " left(mvar, )="+ left(mvar)
? " left(mvar,5)="+ left(mvar,5)
? " left(mvar,11)="+left(mvar,11)
?
? " left_vt(mvar, )="+ left_vt(mvar)
? " left_vt(mvar,5)="+ left_vt(mvar,5)
? " left_vt(mvar,11)="+left_vt(mvar,11)
?
? " left_tr(mvar, )="+ left_tr(mvar)  && will gen a run-time error
? " left_tr(mvar,5)="+ left_tr(mvar,5)
? " left_tr(mvar,11)="+left_tr(mvar,11)
? " All done..."
*
FUNCTION LEFT_TR
* Syntax: LEFT_TR( <expC>, <expN> )
* Return: The leftmost <expN> characters of <expC>
*
PARAMETERS cl_string, cl_len
RETURN SUBSTR(cl_string, 1, cl_len)
*
* NOTE: The above function is the "Tom Rettig" version without error
*       checking for proper parameter passing, the next version does
*       check parameters same as the "Van Tassel " C version of left()
*
FUNCTION LEFT_VT
*
PARAMETERS cl_string, cl_len
IF (PCOUNT()=2).AND.(TYPE("cl_string")="C").AND.(TYPE("cl_len")="N")
  RETURN SUBSTR(cl_string, 1, cl_len)
ELSE
  RETURN "Error..."
ENDIF


