Posted to tcl by emiliano at Wed Apr 29 13:46:16 GMT 2009view raw

  1. here's the extension code (transform.c):
  2.  
  3. 8<----------8<----------8<----------8<----------8<----------
  4.  
  5. /*
  6. * transform.c -- Quickly transform a list for graphing
  7. */
  8. #include <tcl.h>
  9.  
  10. /*
  11. * Transform_Cmd
  12. * this function implements the command and does the transform
  13. */
  14.  
  15. static int
  16. Transform_Cmd (
  17. ClientData cdata,
  18. Tcl_Interp *interp,
  19. int objc,
  20. Tcl_Obj * CONST objv[] )
  21. {
  22. int index, length, result;
  23. double xoffset, xscale, yoffset, yscale, x, y;
  24. Tcl_Obj * xlistPtr, * ylistPtr;
  25. Tcl_Obj * newlist;
  26.  
  27. if (objc != 6) {
  28. Tcl_WrongNumArgs(interp, 1, objv,
  29. "list xoffset xscale yoffsset yscale");
  30. return TCL_ERROR;
  31. }
  32.  
  33. /* The list should have an even number of elements */
  34. result = Tcl_ListObjLength(interp, objv[1], &length);
  35.  
  36. if (result == TCL_ERROR) {
  37. return TCL_ERROR;
  38. }
  39.  
  40. if (length % 2) {
  41. Tcl_SetObjResult(interp,
  42. Tcl_NewStringObj("list should have an even number of elements",-1));
  43. return TCL_ERROR;
  44. }
  45.  
  46. /* Now, the last four parameters need to be doubles */
  47. if ( Tcl_GetDoubleFromObj(interp, objv[2], &xoffset) != TCL_OK
  48. || Tcl_GetDoubleFromObj(interp, objv[3], &xscale) != TCL_OK
  49. || Tcl_GetDoubleFromObj(interp, objv[4], &yoffset) != TCL_OK
  50. || Tcl_GetDoubleFromObj(interp, objv[5], &yscale) != TCL_OK )
  51. {
  52. return TCL_ERROR;
  53. }
  54.  
  55. result = TCL_OK;
  56. newlist = Tcl_NewListObj(0, NULL);
  57. Tcl_IncrRefCount(newlist);
  58.  
  59. for ( index = 0; index < length ; index += 2) {
  60.  
  61. result = Tcl_ListObjIndex(interp, objv[1], index, &xlistPtr);
  62. if (result == TCL_ERROR) break;
  63.  
  64. result = Tcl_GetDoubleFromObj(interp, xlistPtr, &x);
  65. if (result == TCL_ERROR) break;
  66.  
  67. result = Tcl_ListObjIndex(interp, objv[1], index+1, &ylistPtr);
  68. if (result == TCL_ERROR) break;
  69.  
  70. result = Tcl_GetDoubleFromObj(interp, ylistPtr, &y);
  71. if (result == TCL_ERROR) break;
  72.  
  73. Tcl_ListObjAppendElement(
  74. interp, newlist,
  75. Tcl_NewDoubleObj(xoffset + xscale * x));
  76. Tcl_ListObjAppendElement(
  77. interp, newlist,
  78. Tcl_NewDoubleObj(yoffset + yscale * y));
  79. }
  80.  
  81. if (result == TCL_OK) {
  82. Tcl_SetObjResult (interp, newlist);
  83. }
  84.  
  85. Tcl_DecrRefCount(newlist);
  86. return result;
  87. }
  88.  
  89. /*
  90. * Transform_Init -- Called when Tcl loads the extension.
  91. */
  92. int DLLEXPORT
  93. Transform_Init(Tcl_Interp *interp)
  94. {
  95. if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
  96. return TCL_ERROR;
  97. }
  98.  
  99. if (Tcl_PkgProvide(interp, "Transform", "0.1") == TCL_ERROR) {
  100. return TCL_ERROR;
  101. }
  102.  
  103. Tcl_CreateObjCommand(interp, "grafico::transforma_datos", Transform_Cmd, NULL, NULL);
  104.  
  105. return TCL_OK;
  106. }
  107.  
  108.  
  109. 8<----------8<----------8<----------8<----------8<----------
  110.  
  111.  
  112. here's the short Makefile
  113.  
  114. 8<----------8<----------8<----------8<----------8<----------
  115.  
  116. TCL_INCLUDES= -I/usr/local/include
  117. TCL_LIBSPEC= -DUSE_TCL_STUBS -L/usr/local/lib -ltclstub8.6
  118.  
  119. libtransform.so: transform.c
  120. rm -f libtransform.so
  121. gcc -fPIC -shared -o libtransform.so ${TCL_INCLUDES} ${TCL_LIBSPEC} transform.c
  122.  
  123.  
  124. 8<----------8<----------8<----------8<----------8<----------
  125.  
  126.  
  127. after compiling the extension, this is what happens:
  128.  
  129. emiliano@merlot:~/indicador$ tclsh8.6
  130. % load ./libtransform.so
  131. couldn't load file "./libtransform.so": ./libtransform.so: undefined symbol: tclStubsPtr
  132. %