home *** CD-ROM | disk | FTP | other *** search
- *******************************************************************************
- *
- * PROGRAM: dbextern.prg
- *
- * WRITTEN BY: Borland Samples Group
- *
- * DATE: 1/94
- *
- * UPDATED: 5/94
- *
- * REVISION: $Revision: 2.10 $
- *
- * VERSION: Visual dBASE
- *
- * DESCRIPTION: Examples that shows how the EXTERN system can be used.
- *
- * PARAMETERS: Number of example to execute, 0 for all.
- *
- * CALLS: Windows functions and calls to dbextern.dll
- *
- * USAGE: DO dbextern with <example#>
- * Where <example#> can be from 1 to 11, or 0 for all.
- *
- *******************************************************************************
-
- *******************************************************************************
- *
- * Introduction:
- * The EXTERN system is an extension of Visual dBASE that allows
- * Visual dBASE programs to interface with DLL's written in Windows compatible
- * languages. Exported functions from a DLL can be called from a Visual dBASE
- * program and those DLL functions can call back into Visual dBASE using the
- * mechanism of setting and executing codeblocks.
- * DLL functions can be called with arguments of simple type, like numeric,
- * float, and character, but with the inclusion of the "dbasevar.h" file
- * more complex Visual dBASE variables can be passed to functions in a DLL and
- * caught in "DBaseVar" variables. Through these DBaseVar variables the
- * DLL can access and manipulate Visual dBASE variables.
- *
- * General format to declare an EXTERN function:
- *
- * EXTERN [<callconvention>] <returntype> <funcname> | <user defined funcname>
- * ([parameters]) [<path>] <dllname> [FROM <expC> | <expN>]
- * where:
- * <callconvention> = CDECL or nothing for implied PASCAL.
- * <returntype> = One of CVOID | CSTRING | CWORD | CLONG | CLOGICAL |
- * CDOUBLE | CHANDLE | CINT | CVAR.
- * <funcname> = Name of the function you want to call.
- * <user defined funcname> = Name you give to the function. Required if
- * using the FROM option.
- * <parameters> = parameters of the types CSTRING | CWORD | CLONG |
- * CDOUBLE | CPTR | CVAR | CHANDLE | ... | CINT | CVOID |
- * CLOGICAL.
- * <path> = Optional path to DLL, defaults to Windows DLL search path.
- * <dllname> = Name of the DLL that contains the function.
- * FROM <expC> | <expN> = name of the function in the DLL or the ordinal #
- * of the function in the DLL if you rename the
- * function above in <user defined funcname>.
- *
- * NOTE: the CVAR and ... options apply only to DLL's that are written
- * for Visual dBASE using the dbasevar.h file.
- *
- * After the EXTERN statement you can use the function just like any
- * other function in your Visual dBASE statements.
- *
- *
- * Following are examples that show different ways to use the
- * EXTERN system. Most examples have a C/C++ counterpart in the
- * dbextern.cpp file so look there to see how things work in the DLL.
- *
- * Look in the dbasevar.h header file for more information about how
- * Visual dBASE variables are declared and used on the DLL side.
- *
- *******************************************************************************
-
- parameters whichone
-
- set talk off
-
- * Check parameters
-
- tellusage = 1
-
- * Any parameters at all?
- IF pcount() > 0
- * Parameter numeric?
- IF type( "whichone" ) = "N"
- * Parameter in range?
- IF whichone <= 11 .AND. whichone >= 0
- tellusage = 0
- ENDIF
- ENDIF
- ENDIF
-
- IF tellusage = 1
- ? "Usage: do dbextern with <example#>"
- ? "Where <example#> can be from 1 to 11, or 0 for all."
- return
- ENDIF
-
- *******************************************************************************
- *
- * Example # 1.
- *
- * Some simple examples using the different types. Also demonstrates how
- * to use the FROM option using the name of a PASCAL function.
- *
- *******************************************************************************
-
- IF whichone = 1 .or. whichone = 0
-
- EXTERN CLOGICAL TypeTest1( CSTRING,CWORD,CDOUBLE ) dbextern.dll
- EXTERN CLOGICAL T1( CSTRING,CWORD,CDOUBLE ) dbextern.dll FROM "TypeTest1"
- EXTERN CDECL CDOUBLE TypeTest2( CPTR, CLONG, CVAR ) dbextern.dll
-
- ? "TypeTest1( should be .T. ) =", TypeTest1( "string", 123, 321.123 )
- ? "T1( should be .T. ) =", T1( "string", 123, 321.123 )
- d1 = 234.4
- ? "TypeTest2( should be 857.50 ) =", TypeTest2( "123.1", 500, d1 )
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 2.
- *
- * Execute Windows API functions:
- *
- *******************************************************************************
-
- IF whichone = 2 .or. whichone = 0
-
- EXTERN CWORD MessageBox( CWORD, CSTRING, CSTRING, CWORD ) user.exe
- EXTERN CWORD GetFocus() user.exe
-
- MessageBox( GetFocus(), "Hello", "Message", 0 )
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 3.
- *
- * The Visual dBASE objects you send as CVAR's can be of various types.
- * In the DLL you can get the type of the object with Type().
- *
- *******************************************************************************
-
- IF whichone = 3 .or. whichone = 0
-
- EXTERN CSTRING WhichType( CVAR ) dbextern.dll
-
- o = .T.
- ? ".T.:", WhichType( o )
- o = 123.4
- ? "123.4:", WhichType( o )
- o = 1234
- ? "1234:", WhichType( o )
- o = "hello"
- ? "'hello':", WhichType( o )
- o = new object()
- ? "new object():", WhichType( o )
- o = {|a| a=a }
- ? "{|a| a=a}:", WhichType( o )
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 4.
- *
- * Visual dBASE variables are passed by reference and are caught on the
- * DLL side with a DBaseVar *. This makes it possible to modify
- * Visual dBASE objects in the DLL. This example also demonstrates how
- * to use the CVAR type as the return type of functions. In the
- * source code of the DLL there are some hints on how to set up
- * the prototypes for the corresponding C/C++ functions.
- *
- *******************************************************************************
-
- IF whichone = 4 .or. whichone = 0
-
- * We'll do a CDECL and a PASCAL function.
- EXTERN CDECL CVAR ModifyAndAdd1( CVAR, CVAR ) dbextern.dll
- EXTERN CVAR ModifyAndAdd2( CVAR, CVAR ) dbextern.dll
-
- d1 = 2.5
- d2 = 3
- result = .F.
- result = ModifyAndAdd1( d1, d2 )
- ? "d1 before 2.5, after", d1
- ? "d2 before 3, after", d2
- ? "result before .F., after", result
-
- d1 = 2.5
- d2 = 3
- result = .F.
- result = ModifyAndAdd2( d1, d2 )
- ? "d1 before 2.5, after", d1
- ? "d2 before 3, after", d2
- ? "result before .F., after", result
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 5.
- *
- * Members of a class object passed to a DLL are also accessible.
- * This leads to one way to execute Windows API functions that require
- * structs as parameters. Here we call into a DLL that translates the
- * Visual dBASE class object into a C struct and does the actual calling. The
- * result of the call is piped back into a Visual dBASE object.
- *
- *******************************************************************************
-
- IF whichone = 5 .or. whichone = 0
-
- EXTERN CDECL CVOID WSetRect( CVAR,CWORD,CWORD,CWORD,CWORD ) dbextern.dll
- EXTERN CVOID WIntersectRect( CVAR,CVAR,CVAR ) dbextern.dll
-
- r1 = new Rect()
- r2 = new Rect()
- r3 = new Rect()
- WSetRect( r1, 10,20,100,200 )
- WSetRect( r2, 50,60,150,260 )
- WIntersectRect( r3, r1, r2 )
- ? "Rect after intersect:"
- ? r3.left, r3.top, r3.right, r3.bottom
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 6.
- *
- * Through the use of code blocks Visual dBASE code can be executed on the fly
- * from inside the DLL. This example passes 2 objects and through code
- * blocks the objects are compared and changed in the DLL.
- *
- *******************************************************************************
-
- IF whichone = 6 .or. whichone = 0
-
- EXTERN CSTRING CheckAndChange( CVAR, CVAR ) dbextern.dll
-
- a = 5; b = 5
- ? CheckAndChange( a, b )
- ? "a and b =", a, b
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 7.
- *
- * Visual dBASE arrays can be accessed in the DLL. This example computes the
- * average of the members of an array created on the Visual dBASE side.
- * The DLL function is called without any parameters. To be able to
- * get at the array, the DLL function is executed through a function
- * pointer that is a member of the same object as the array. Inside
- * the DLL you can get the "this" pointer of the object the calling
- * functionptr belongs to, and through that "this" pointer you can
- * access the array members.
- * Normally ofcourse you can just pass the array as a CVAR.
- *
- *******************************************************************************
-
- IF whichone = 7 .or. whichone = 0
-
- EXTERN CDECL CDOUBLE ComputeAverage() dbextern.dll
-
- d = new array( 5 )
- d.average = ComputeAverage
- d[1] = 1.1
- d[2] = 2.2
- d[3] = 3.3
- d[4] = 4.4
- ? "Computed average:", d.average()
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 8.
- *
- * This example puts into "practice" a majority of the available
- * memberfunctions of the DBaseVar class. Not much to see on this side,
- * but check out the corresponding function in the DLL.
- *
- *******************************************************************************
-
- IF whichone = 8 .or. whichone = 0
-
- EXTERN CLONG TestABunch( CVAR ) dbextern.dll
-
- p = new object()
- ? "TestABunch Errors:", TestABunch( p )
- ? "row one of array p:", p[1,1], p[1,2], p[1,3]
- ? "row two of array p:", p[2,1], p[2,2], p[2,3]
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 9.
- *
- * If a DLL is written in a language that can talk to DOS, you can take
- * advantage of that. This example gets the complete DOS environment in
- * one big string. The FROM option using ordinals is also used. Ordinal
- * 14 refers to GetEnvString as can be seen in the dbextern.def file.
- *
- *******************************************************************************
-
- IF whichone = 9 .or. whichone = 0
-
- EXTERN CDECL CVOID GetEnvString( CVAR ) dbextern.dll
- EXTERN CDECL CVOID Getit( CVAR ) dbextern.dll FROM 14
-
- q1 = new object()
- GetEnvString( q1 )
- q2 = new object()
- Getit( q2 )
- ? "First 40 chars of environment:"
- ? substr( q1,1,20 ) + substr( q2,21,20 )
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 10.
- *
- * This example shows how variable number of parameters can be implemented
- * for CDECL functions, and how the FROM option works with CDECL functions.
- *
- *******************************************************************************
-
- IF whichone = 10 .or. whichone = 0
-
- EXTERN CDECL CDOUBLE AddNumbers(...) dbextern.dll
- EXTERN CDECL CDOUBLE AddThem(...) dbextern.dll FROM "_AddNumbers"
-
- a = 1.1
- b = 2.2
- c = 3.3
- ? "AddNumber(...) should be 6.60:",AddNumbers( a, b, c )
-
- a = 2.1
- b = 3.2
- c = 4.3
- ? "AddThem(...) should be 9.60:",AddThem( a, b, c )
-
- ENDIF
-
- *******************************************************************************
- *
- * Example # 11.
- *
- * This example shows how a Visual dBASE object can be combined with an "hidden"
- * C++ sister object. Each Visual dBASE object has its own unique C++ object.
- * This allows a Visual dBASE object to "remember and store" its own details
- * specific to the DLL in the C++ object instead of having to save it
- * in the Visual dBASE object. Examples are the storing of filehandles, and
- * filepointers when the DLL is servicing files.
- * Another possibility is a form of late binding where at the time of
- * creation of the C++ part a choice can be made from several derived
- * classes based on a common parent object.
- *
- *******************************************************************************
-
- IF whichone = 11 .or. whichone = 0
-
- EXTERN CWORD DLLObjectInit( CWORD ) dbextern.dll
- EXTERN CSTRING Doit() dbextern.dll
- EXTERN CVOID Release() dbextern.dll
-
- * Create 2 objects that bind with the same C++ class.
- foo1 = new dBASEObject()
- foo2 = new dBASEObject()
- foo1.init( 1 )
- foo2.init( 1 )
- * One more object that binds with a different C++ class.
- bar = new dBASEObject()
- bar.init( 2 )
-
- * The first 2 object have different information stored but
- * behave similarly.
- ? "foo1.doit():", foo1.doit()
- ? "foo2.doit():", foo2.doit()
-
- * The last one has different info AND behaves differently.
- ? "bar.doit():", bar.doit()
-
- foo1.release()
- foo2.release()
- bar.release()
-
- ENDIF
-
- *******************************************************************************
- *
- * Class definitions.
- *
- *******************************************************************************
-
- class Rect
- this.left=0
- this.top=0
- this.right=0
- this.bottom=0
- endclass
-
- class dBASEObject
- this.init = DLLObjectInit
- this.doit = Doit
- this.release = Release
- endclass
-
- ********************* End of dbextern.prg ************************************
-