FoxProFoxPro Developer's Conference '94 |
Session
114
Objectoriented extensions
with LCK and VC++
Calvin Hsia
Calvin Hsia Consulting
Overview
We all know that Microsoft Foxpro is a very powerful language. Ever since version 1.0 of Foxbase, the Fox language has been procedural. The next version of Foxpro is due out in a few months. It will have object oriented extensions to the language. Using OOP is a major paradigm shift from programming in procedural code. If you have the Professional version of Foxpro 2.6, then you already have the means to explore OOP via the LCK.
Requirements
With the professional version of 2.6, the Library Construction Kit is included. It allows you to extend the power of Foxpro by calling your C and C++ functions. Those functions, in turn can call back into Foxpro, making a very powerful combination.
Youll also need a 16 bit C++ compiler, such as MSVC 1.5. This will allow you to create C and C++ programs for the DOS & Windows environment. For the next version of Foxpro, youll need a 32 bit C/C++ compiler, such as MSVC2.0.
If youre a serious developer, youll probably also want to run under Win NT. Its a far more stable environment for software development. Each task is given its own virtual 4 gigabyte address space, in which it is impossible to corrupt other tasks.
Getting Started
Heres a simple program that creates a table and adds 100 records to it. Note that this is a C++ program.
#include "pro_ext.h" void MyFunction(ParamBlk *p) { int i; _Execute("wait window 'Executing'"); _Execute("close all"); _Execute("create cursor customer (name c(10), address c(10))"); for (i=0 ; i<100 ; i++) { _Execute("insert into customer values ('Fred','123 anywhere')"); } _Execute("browse"); } void Initialize(void) { _Execute("wait window nowait 'init'"); } void UnInitialize(void) { _Execute("wait window nowait 'init'"); } FoxInfo myFoxInfo[] = { {"INITIALIZE" , (FPFI) Initialize, CALLONLOAD, ""}, {"UNINITALIZE", (FPFI) UnInitialize,CALLONUNLOAD, ""}, {"MYFUNCTION" , (FPFI) MyFunction,1,".C"} }; extern "C" FoxTable _FoxTable = { (FoxTable FAR *)0, sizeof(myFoxInfo)/ sizeof(FoxInfo), myFoxInfo };
C vs C++
In C++, function names are "mangled" in order to accomodate polymorphism. That means there can be a function called FOO( int i1,int i2) that takes 2 integer parameters, and there can be a totally different function FOO(int I1, char *p) that takes an integer parameter and a pointer to a string. Internally, the C++ compiler will append a suffix to the function name that describes the parameters. That allows the linker to be able to resolve function calls according to the parameter types.
The Foxpro LCK expects a C table called FoxTable to exist within the FLL. If your program is compiled with a "CPP" extension, then the compiler automatically compiles it as a C++ function, with name mangling. In order to prevent the name mangling, so the Linker can link Foxpro and your function together, you need to precede the function with {extern "C"}.
Our First Object
Well create a string object as our first object. As some of you know, C and C++ do not have native support for strings. A string is typically represented as an array of Chars. Perhaps a terminating NULL indicates its length, or the first byte might contain the length. With OOP, we can create a class of string objects. Then the rest of our program can create string objects from this class, manipulate them as needed, and destroy them when no longer needed. The internal structure/processes of the string object are hidden from the user, and thus encapsulation is achieved. For example, in order to use strings with Foxpro, we can allocate string storage from the Foxpro memory manager. Or, we can allocate a fixed amount of space from the data segment. the route taken for implementation is hidden from the user, and can be changed later with minimal impact on the users code.
Heres a sample:
#include "pro_ext.h" #include "string.h" class MyStr { private: MHANDLE mh; int len; public: MyStr(char *s); //constructor void show(); }; MyStr::MyStr(char *s) { len=strlen(s); mh=_AllocHand(len); char *ptr=(char *)_HandToPtr(mh); _MemMove(ptr,s,len); _HUnLock(mh); } void MyStr::show() { Value myval; myval.ev_handle=mh; myval.ev_length=len; myval.ev_type='C'; _PutValue(&myval); } void MyFunction(ParamBlk *p) { int i; _Execute("wait window nowait 'Executing'"); _Execute("close all"); _Execute("create cursor customer (name c(10), address c(10))"); for (i=0 ; i<100 ; i++) { _Execute("insert into customer values ('Fred','123 anywhere')"); } _Execute("browse"); MyStr thisstr("testing"); thisstr.show(); } void Initialize(void) { _Execute("wait window nowait 'init'"); } void UnInitialize(void) { _Execute("wait window nowait 'init'"); } FoxInfo myFoxInfo[] = { {"INITIALIZE" , (FPFI) Initialize, CALLONLOAD, ""}, {"UNINITALIZE", (FPFI) UnInitialize,CALLONUNLOAD, ""}, {"MYFUNCTION" , (FPFI) MyFunction,1,".C"} }; extern "C" FoxTable _FoxTable = { (FoxTable FAR *)0, sizeof(myFoxInfo)/ sizeof(FoxInfo), myFoxInfo };
Our Second Object
Using a linked list to store information is very handy. Well create a simple singly linked list, using our First Object as a basis. We can pass a parameter to a function to add objects to the linked list, and have another function display all the objects in the list.
Create your own objects
You can learn a lot about object oriented programming by actually creating and using objects in a real world application. Explore the differences between OOP and procedural programming. Before the next version of Foxpro is released, youll have a headstart at creating OOP programs. Above all, have fun!
Object-oriented extensions with LCK and VC++
(c)1994 Calvin Hsia