home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD 24 / PCPLUS115.iso / install / extern.pak / DBEXTERN.PRG < prev    next >
Encoding:
Text File  |  1994-08-02  |  13.2 KB  |  419 lines

  1. *******************************************************************************
  2. *
  3. *  PROGRAM:      dbextern.prg
  4. *
  5. *  WRITTEN BY:   Borland Samples Group
  6. *
  7. *  DATE:         1/94
  8. *
  9. *  UPDATED:      3/94
  10. *
  11. *  VERSION:      Field Test March 94
  12. *
  13. *  DESCRIPTION:  Examples that shows how the EXTERN system can be used.
  14. *
  15. *  PARAMETERS:   Number of example to execute, 0 for all.
  16. *
  17. *  CALLS:        Windows functions and calls to dbextern.dll
  18. *
  19. *  USAGE:        DO dbextern with <example#>
  20. *                Where <example#> can be from 1 to 11, or 0 for all.
  21. *
  22. *
  23. *******************************************************************************
  24.  
  25. *******************************************************************************
  26. *
  27. * Introduction:
  28. * The EXTERN system is an extension of dBASE for Windows that allows
  29. * dBASE programs to interface with DLL's written in Windows compatible
  30. * languages.  Exported functions from a DLL can be called from a dBASE 
  31. * program and those DLL functions can call back into dBASE using the
  32. * mechanism of setting and executing codeblocks.
  33. * DLL functions can be called with arguments of simple type, like numeric,
  34. * float, and character, but with the inclusion of the "dbasevar.h" file
  35. * more complex dBASE variables can be passed to functions in a DLL and 
  36. * caught in "DBaseVar" variables.  Through these DBaseVar variables the
  37. * DLL can access and manipulate dBASE variables.
  38. *
  39. * General format to declare an EXTERN function:
  40. *
  41. * EXTERN [<callconvention>] <returntype> <funcname> | <user defined funcname>
  42. *        ([parameters]) [<path>] <dllname> [FROM <expC> | <expN>]
  43. * where: 
  44. * <callconvention> = CDECL or nothing for implied PASCAL.
  45. * <returntype> = One of CVOID | CSTRING | CWORD | CLONG | CLOGICAL | 
  46. *                       CDOUBLE | CHANDLE | CINT | CVAR.
  47. * <funcname> = Name of the function you want to call.    
  48. * <user defined funcname> = Name you give to the function. Required if
  49. *                           using the FROM option.
  50. * <parameters> = parameters of the types CSTRING | CWORD | CLONG |
  51. *                CDOUBLE | CPTR | CVAR | CHANDLE | ... | CINT | CVOID |
  52. *                CLOGICAL.
  53. * <path> = Optional path to DLL, defaults to Windows DLL search path.
  54. * <dllname> = Name of the DLL that contains the function.
  55. * FROM <expC> | <expN> = name of the function in the DLL or the ordinal #
  56. *                        of the function in the DLL if you rename the
  57. *                        function above in <user defined funcname>.
  58. *
  59. * NOTE: the CVAR and ... options apply only to DLL's that are written
  60. *       for dBASE using the dbasevar.h file.
  61. *
  62. * After the EXTERN statement you can use the function just like any
  63. * other function in your dBASE statements.
  64. *
  65. * Following are examples that show different ways to use the 
  66. * EXTERN system.  Most examples have a C/C++ counterpart in the
  67. * dbextern.cpp file so look there to see how things work in the DLL.
  68. *
  69. * Look in the dbasevar.h header file for more information about how
  70. * dBASE variables are declared and used on the DLL side.
  71. *
  72. *******************************************************************************
  73.  
  74. parameters whichone
  75.  
  76. set talk off
  77.  
  78.  * Check parameters
  79.  
  80. tellusage = 1
  81.  
  82.  * Any parameters at all?
  83. IF pcount() > 0
  84.     * Parameter numeric?
  85.    IF type( "whichone" ) = "N"
  86.         * Parameter in range?
  87.        IF whichone <= 11 .AND. whichone >= 0
  88.            tellusage = 0
  89.        ENDIF
  90.    ENDIF
  91. ENDIF
  92.  
  93. IF tellusage = 1  
  94.    ? "Usage: do dbextern with <example#>"
  95.    ? "Where <example#> can be from 1 to 11, or 0 for all."
  96.    return
  97. ENDIF
  98.  
  99. *******************************************************************************
  100. *
  101. * Example # 1.
  102. *
  103. * Some simple examples using the different types.  Also demonstrates how
  104. * to use the FROM option using the name of a PASCAL function.
  105. *******************************************************************************
  106.  
  107. IF whichone = 1 .or. whichone = 0
  108.  
  109.    EXTERN CLOGICAL TypeTest1( CSTRING,CWORD,CDOUBLE ) dbextern.dll 
  110.    EXTERN CLOGICAL T1( CSTRING,CWORD,CDOUBLE ) dbextern.dll FROM "TypeTest1"
  111.    EXTERN CDECL CDOUBLE TypeTest2( CPTR, CLONG, CVAR ) dbextern.dll 
  112.  
  113.    ? "TypeTest1( should be .T. ) =", TypeTest1( "string", 123, 321.123 )
  114.    ? "T1( should be .T. ) =", T1( "string", 123, 321.123 )
  115.    d1 = 234.4
  116.    ? "TypeTest2( should be 857.50 ) =", TypeTest2( "123.1", 500, d1 )
  117.  
  118. ENDIF
  119.  
  120. *******************************************************************************
  121. *
  122. * Example # 2.
  123. *
  124. * Execute Windows API functions:
  125. *******************************************************************************
  126.  
  127. IF whichone = 2 .or. whichone = 0
  128.  
  129.    EXTERN CWORD MessageBox( CWORD, CSTRING, CSTRING, CWORD ) user.exe
  130.    EXTERN CWORD GetFocus() user.exe
  131.  
  132.    MessageBox( GetFocus(), "Hello", "Message", 0 )
  133.  
  134. ENDIF
  135.  
  136. *******************************************************************************
  137. *
  138. * Example # 3.
  139. *
  140. * The dBASE objects you send as CVAR's can be of various types.
  141. * In the DLL you can get the type of the object with Type().
  142. *******************************************************************************
  143.  
  144. IF whichone = 3 .or. whichone = 0
  145.  
  146.    EXTERN CSTRING WhichType( CVAR ) dbextern.dll
  147.  
  148.    o = .T.
  149.    ? ".T.:", WhichType( o )
  150.    o = 123.4
  151.    ? "123.4:", WhichType( o )
  152.    o = 1234
  153.    ? "1234:", WhichType( o )
  154.    o = "hello"
  155.    ? "'hello':", WhichType( o )
  156.    o = new object()
  157.    ? "new object():", WhichType( o )
  158.    o = {|a| a=a }
  159.    ? "{|a| a=a}:", WhichType( o )
  160.  
  161. ENDIF
  162.  
  163. *******************************************************************************
  164. *
  165. * Example # 4.
  166. *
  167. * dBASE variables are passed by reference and are caught on the 
  168. * DLL side with a DBaseVar *.  This makes it possible to modify
  169. * dBASE objects in the DLL.  This example also demonstrates how
  170. * to use the CVAR type as the return type of functions.  In the
  171. * source code of the DLL there are some hints on how to set up
  172. * the prototypes for the corresponding C/C++ functions.
  173. *******************************************************************************
  174.  
  175. IF whichone = 4 .or. whichone = 0
  176.  
  177.        * We'll do a CDECL and a PASCAL function.
  178.    EXTERN CDECL CVAR ModifyAndAdd1( CVAR, CVAR ) dbextern.dll
  179.    EXTERN CVAR ModifyAndAdd2( CVAR, CVAR ) dbextern.dll
  180.  
  181.    d1 = 2.5
  182.    d2 = 3
  183.    result = .F.
  184.    result = ModifyAndAdd1( d1, d2 )
  185.    ? "d1 before 2.5,     after", d1
  186.    ? "d2 before 3,       after", d2
  187.    ? "result before .F., after", result
  188.  
  189.    d1 = 2.5
  190.    d2 = 3
  191.    result = .F.
  192.    result = ModifyAndAdd2( d1, d2 )
  193.    ? "d1 before 2.5,     after", d1
  194.    ? "d2 before 3,       after", d2
  195.    ? "result before .F., after", result
  196.  
  197. ENDIF
  198.  
  199. *******************************************************************************
  200. *
  201. * Example # 5.
  202. *
  203. * Members of a class object passed to a DLL are also accessible.
  204. * This leads to one way to execute Windows API functions that require 
  205. * structs as parameters.  Here we call into a DLL that translates the 
  206. * dBASE class object into a C struct and does the actual calling. The
  207. * result of the call is piped back into a dBASE object.
  208. *
  209. *******************************************************************************
  210.  
  211. IF whichone = 5 .or. whichone = 0
  212.  
  213.    EXTERN CDECL CVOID WSetRect( CVAR,CWORD,CWORD,CWORD,CWORD ) dbextern.dll
  214.    EXTERN CVOID WIntersectRect( CVAR,CVAR,CVAR ) dbextern.dll
  215.  
  216.    r1 = new Rect()
  217.    r2 = new Rect()
  218.    r3 = new Rect()
  219.    WSetRect( r1, 10,20,100,200 )
  220.    WSetRect( r2, 50,60,150,260 )
  221.    WIntersectRect( r3, r1, r2 )
  222.    ? "Rect after intersect:"
  223.    ? r3.left, r3.top, r3.right, r3.bottom
  224.  
  225. ENDIF
  226.  
  227. *******************************************************************************
  228. *
  229. * Example # 6.
  230. *
  231. * Through the use of code blocks dBASE code can be executed on the fly
  232. * from inside the DLL.  This example passes 2 objects and through code
  233. * blocks the objects are compared and changed in the DLL.
  234. *
  235. *******************************************************************************
  236.  
  237. IF whichone = 6 .or. whichone = 0
  238.  
  239.    EXTERN CSTRING CheckAndChange( CVAR, CVAR ) dbextern.dll
  240.  
  241.    a = 5; b = 5
  242.    ? CheckAndChange( a, b )
  243.    ? "a and b =", a, b
  244.  
  245. ENDIF
  246.  
  247. *******************************************************************************
  248. *
  249. * Example # 7.
  250. *
  251. * dBASE arrays can be accessed in the DLL.  This example computes the
  252. * average of the members of an array created on the dBASE side.
  253. * The DLL function is called without any parameters.  To be able to
  254. * get at the array, the DLL function is executed through a function
  255. * pointer that is a member of the same object as the array.  Inside
  256. * the DLL you can get the "this" pointer of the object the calling
  257. * functionptr belongs to, and through that "this" pointer you can 
  258. * access the array members.
  259. * Normally ofcourse you can just pass the array as a CVAR.
  260. *
  261. *******************************************************************************
  262.  
  263. IF whichone = 7 .or. whichone = 0
  264.  
  265.    EXTERN CDECL CDOUBLE ComputeAverage() dbextern.dll
  266.  
  267.    d = new array( 5 )
  268.    d.average = ComputeAverage
  269.    d[1] = 1.1
  270.    d[2] = 2.2
  271.    d[3] = 3.3
  272.    d[4] = 4.4
  273.    ? "Computed average:", d.average()
  274.  
  275. ENDIF
  276.  
  277. *******************************************************************************
  278. *
  279. * Example # 8.
  280. *
  281. * This example puts into "practice" a majority of the available 
  282. * memberfunctions of the DBaseVar class.  Not much to see on this side, 
  283. * but check out the corresponding function in the DLL.
  284. *******************************************************************************
  285.  
  286. IF whichone = 8 .or. whichone = 0
  287.  
  288.    EXTERN CLONG TestABunch( CVAR ) dbextern.dll
  289.  
  290.    p = new object()
  291.    ? "TestABunch Errors:", TestABunch( p )
  292.    ? "row one of array p:", p[1,1], p[1,2], p[1,3]
  293.    ? "row two of array p:", p[2,1], p[2,2], p[2,3]
  294.  
  295. ENDIF
  296.  
  297. *******************************************************************************
  298. *
  299. * Example # 9.
  300. *
  301. * If a DLL is written in a language that can talk to DOS, you can take
  302. * advantage of that.  This example gets the complete DOS environment in
  303. * one big string.  The FROM option using ordinals is also used. Ordinal
  304. * 14 refers to GetEnvString as can be seen in the dbextern.def file. 
  305. *
  306. *******************************************************************************
  307.  
  308. IF whichone = 9 .or. whichone = 0
  309.  
  310.    EXTERN CDECL CVOID GetEnvString( CVAR ) dbextern.dll 
  311.    EXTERN CDECL CVOID Getit( CVAR ) dbextern.dll FROM 14
  312.  
  313.    q1 = new object()
  314.    GetEnvString( q1 )
  315.    q2 = new object()
  316.    Getit( q2 )
  317.    ? "First 40 chars of environment:"
  318.    ? substr( q1,1,20 ) + substr( q2,21,20 )
  319.  
  320. ENDIF
  321.  
  322. *******************************************************************************
  323. *
  324. * Example # 10.
  325. *
  326. * This example shows how variable number of parameters can be implemented
  327. * for CDECL functions, and how the FROM option works with CDECL functions.
  328. *
  329. *******************************************************************************
  330.  
  331. IF whichone = 10 .or. whichone = 0
  332.  
  333.    EXTERN CDECL CDOUBLE AddNumbers(...) dbextern.dll
  334.    EXTERN CDECL CDOUBLE AddThem(...) dbextern.dll FROM "_AddNumbers"
  335.  
  336.    a = 1.1
  337.    b = 2.2
  338.    c = 3.3
  339.    ? "AddNumber(...) should be 6.60:",AddNumbers( a, b, c )
  340.  
  341.    a = 2.1
  342.    b = 3.2
  343.    c = 4.3
  344.    ? "AddThem(...) should be 9.60:",AddThem( a, b, c )
  345.  
  346. ENDIF
  347.  
  348. *******************************************************************************
  349. *
  350. * Example # 11.
  351. *
  352. * This example shows how a dBASE object can be combined with an "hidden"
  353. * C++ sister object.  Each dBASE object has its own unique C++ object.
  354. * This allows a dBASE object to "remember and store" its own details 
  355. * specific to the DLL in the C++ object instead of having to save it
  356. * in the dBASE object. Examples are the storing of filehandles, and 
  357. * filepointers when the DLL is servicing files.
  358. * Another possibility is a form of late binding where at the time of 
  359. * creation of the C++ part a choice can be made from several derived 
  360. * classes based on a common parent object. 
  361. *
  362. *******************************************************************************
  363.  
  364. IF whichone = 11 .or. whichone = 0
  365.  
  366.    EXTERN CWORD DLLObjectInit( CWORD ) dbextern.dll
  367.    EXTERN CSTRING Doit() dbextern.dll
  368.    EXTERN CVOID Release() dbextern.dll
  369.  
  370.     * Create 2 objects that bind with the same C++ class.
  371.    foo1 = new dBASEObject()
  372.    foo2 = new dBASEObject()
  373.    foo1.init( 1 )
  374.    foo2.init( 1 )
  375.     * One more object that binds with a different C++ class.
  376.    bar = new dBASEObject()
  377.    bar.init( 2 )
  378.  
  379.     * The first 2 object have different information stored but
  380.     * behave similarly.
  381.    ? "foo1.doit():", foo1.doit()
  382.    ? "foo2.doit():", foo2.doit()
  383.  
  384.     * The last one has different info AND behaves differently.
  385.    ? "bar.doit():", bar.doit()
  386.  
  387.    foo1.release()
  388.    foo2.release()
  389.    bar.release()
  390.  
  391. ENDIF
  392.  
  393. *******************************************************************************
  394. *
  395. * Class definitions.
  396. *
  397. *******************************************************************************
  398.  
  399. class Rect
  400.     this.left=0
  401.     this.top=0
  402.     this.right=0
  403.     this.bottom=0
  404. endclass
  405.  
  406. class dBASEObject
  407.    this.init = DLLObjectInit
  408.    this.doit = Doit
  409.    this.release = Release
  410. endclass
  411.  
  412. ********************* End of dbextern.prg ************************************
  413.