Sample to demonstrate [parameter passing to] and [return from] C functions which are not "pascal", as expected by GFA $XREF compiler directive. C portions compiled with MS Quick C, but should work with MS C. Linked using GFA dgenx for DOS, but should work in windows version. These are the results of trial and error. They are submitted without warranty for experimentation, use, and comments by those seeking to explore the capability limits of GFA Basic. B.D.D. 9/16/95 Listings in this file: np.gfa .... gfa source demonstrating calls to non-pascal c functions npc.c .... c source for linking to np.gfa // ****************** GFA basic listing begins here ********** // np.gfa // program to demonstrate methods of calling non-pascal c functions // using $XREF or C: ' ' Note: ' All external function calls by GFA Basic are "long far pascal." ' C- declared functions require the caller to reset the stack pointer after ' return. Pascal-declared functions require the called function to ' correct the stack pointer before return. ' ' This program uses GFA Basic's $XREF in a "prototype function" (see listing) ' to call a C_decl function using pascal conventions. As a result neither ' party adjusts the stack, and it grows with each call until the program ' design provides for a stack correction, or until the stack overflows. ' ' If your program makes a large number of calls to C_decl functions, ' you can prevent stack overflow by putting one or more of those calls ' in a separate GFA "stack reset function", such as FUNCTION test10(), ' which calls the "prototype function". Each time GFA returns from test10(), ' GFA code will automatically correct the error in the stack pointer. ' Without a "stack reset function", if you don't overflow the stack, ' GFA should correct the stack pointer on exit from the program. ' ' In my rather crude tests, GFA PROCEDUREs failed fatally (EMM386 error) ' when used as stack reset routines, unless the call to the prototype ' function was inside a loop (ie: DO {} UNTIL TRUE) within the procedure. ' FUNCTION always worked in my tests, but its reliability for this purpose is ' uncertain. FUNCTION must explicitly return a value, even if it is a dummy variable ' or 0, unless it is a "prototype function." ' ' This method could be used to eliminate recompiling of C routines as Pascal. ' Another alternative would be to use C:addr%(), which is faster but less convenient, and ' does not assert a function prototype for parameter passing, ' $LNK OBJ npc.obj //link to c object file $LNK EXE np.exe // make exe file $LNK MAP np.map // make a map file cls OPENW#1 INPUT "About to call external function, hit enter ";a$ ? a%=@test10() PRINT a%;" = returned value from C_decl function nptest1 using $XREF" a%= @test2(1,2,3,4,5) PRINT a%;" = returned value from Pascal function Nptest2 using $XREF" addr%=@getaddr() a%=C:addr%(1,2,3,4,5) PRINT a%;" = returned value from c_decl function nptest1 using C:" ? ? ? "14 indicates params read right to left from stack (backward)" ? "10 indicates left to right (correctly)" ? INPUT "Done, hit enter";a$ CLOSEW#1 END FUNCTION getaddr() // get address of test1() from c routine $XREF getaddr ENDFUNC FUNCTION test1(z&,y&,x&,w&,v&) ' ******************************* prototype function ' $XREF _nptest1 // pascal call to C function nptest // precede fn name with "_" to conform to default C function name storage. // parms will be received in reverse order from order sent. ENDFUNC FUNCTION test2(z&,y&,x&,w&,v&) '****************************** prototype function ' $XREF Nptest2 // pascal call to pascal function ENDFUNC FUNCTION test10() '***************************** stack pointer reset function ' return value may be dummy value, but must have return. RETURN @test1(1,2,3,4,5) // call to prototype module ENDFUNC PROCEDURE test10() '********** example of how to use a procedure for stack pointer reset ' call to prototye function must be in a loop DO a%=@test1(1,2,3,4,5) UNTIL TRUE RETURN // ****************** C program listing begins here ************** // npc.c // C program to demonstrate passing parameters to non-pascal function long far nptest1(int a,int b,int c,int d,int e) { return (a+b+c+d); } long far pascal Nptest2(int a,int b,int c,int d,int e) { return (a+b+c+d); } long far pascal getaddr() { /* get address of nptest1 for use by C: call in GFA */ return (&nptest1); } // To compile, do not use pascal options. Compile as // qcl /Ox /AL /c npc.c // note: qcl = microsoft quick c command line compiler. // cl should be same