[mod.amiga.sources] C functions and Basic

doc@pucc-j.UUCP (06/28/86)

Reply-To: ihnp4!cbmvax!carolyn@ecn (Carolyn Scheppner)


   Here is one way to call functions written in C from AmigaBasic.
Fun.c contains a couple of specially written functions and CFunTest
is an AmigaBasic program that LoadSeg()s and CALLs them.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Carolyn Scheppner -- CBM   >>Amiga Technical Support<<
                     UUCP  ...{allegra,caip,ihnp4,seismo}!cbmvax!carolyn 
                     PHONE 215-431-9180
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
---------------------------------------------------------------------
/* Fun.c -- C functions to be LoadSeg()'d and called from another program.
            Compiled with no Stack checking (-v option on LC2)
            Linked only with Amiga.lib  (no startup code)
            Calling program must:
               LoadSeg the executable file of this program.
               Segment ptr returned by LoadSeg * 4 + 4 = address of main()
               Caller must allocate a LONG variable for function result
               Caller calls main() passing ptr to LONG result variable
               Main() puts address of JumpTable in result variable
               Caller may then call these functions via their addresses

            Note that first arg for each function is address of the
               LONG where return value may be stashed.

            Also note that because these are not LIBRARY functions,
               they can not be DECLARED in AmigaBasic and therefore
               cannot return a value (since CALL must be used).
               Each function must be declared as void and must
               not attempt to return a value to AmigaBasic or
               stack corruption will result.

            Fun1 moves the screen, waits, then moves it back.
            Fun2 doubles the number it is passed.
*/

#include <exec/types.h>
#include <intuition/intuition.h>

extern void Fun1(), Fun2();  /* So JumpTable can be built */

typedef void (*PFV)();
PFV JumpTable[] = { Fun1, Fun2 };    /* JumpTable of function addresses */

extern ULONG AbsExecBase;
ULONG  SysBase;
ULONG  DOSBase;
struct IntuitionBase *IntuitionBase;

void main(resultPtr)
LONG *resultPtr;
   {
   /* Set up globals SysBase and DOSBase */
   SysBase = (ULONG)AbsExecBase;
   if ((DOSBase = (ULONG)OpenLibrary("dos.library",0))==NULL)
      {
      *resultPtr = 0;
      }
   else
      {
      CloseLibrary(DOSBase);   /* We just needed the pointer */

      *resultPtr = (LONG)&JumpTable[0];
      }
   }



void Fun1(resultPtr,delta)
LONG *resultPtr;
LONG delta;
   {
   struct Screen *frontScreen;

   if ((IntuitionBase =
      (struct IntuitionBase *)OpenLibrary("intuition.library",0))==NULL)
      {
      *resultPtr = 0;
      }
   else
      {
      frontScreen = IntuitionBase->FirstScreen;
      MoveScreen(frontScreen,0,delta);
      Delay(50);
      MoveScreen(frontScreen,0,-delta);

      CloseLibrary(IntuitionBase);
      *resultPtr = delta;
      }
   }





void Fun2(resultPtr,arg1)
LONG *resultPtr;
LONG arg1;
   {
   arg1 += arg1;
   *resultPtr = arg1;
   }




---------------------------------------------------------------------
REM - CFunTest
REM - This program shows how to
REM - use AmigaDOS library routines
REM - to load and call specially
REM - written C functions.  See
REM - Fun.c for more info.
REM - Note 1st arg for each function
REM -  is address of Result& where
REM -  return value is stored.
REM - Because non-LIBRARY functions
REM - cannot be DECLAREed, they must
REM - be CALLed and therefore cannot
REM - directly return a value.

REM *** Result& for return values ***
Result& = 0
                   
DECLARE FUNCTION LoadSeg&  LIBRARY
DECLARE FUNCTION IoErr&    LIBRARY

PRINT "Looking for dos.bmap ... ";
LIBRARY "dos.library"
PRINT "found it."

REM *** LoadSeg the function code  ***
REM *** Address of InitRtn& (main) ***
REM ***  is (SegBptr& * 4) + 4     ***

Filename$ = "Fun"
Loadname$ = Filename$+CHR$(0)
SegBptr& = LoadSeg&(SADD(Loadname$))
IF (SegBptr& = 0) THEN
   PRINT "LoadSeg of "Filename$" failed"
   LoadErr% = IoErr&
   PRINT "IO error ="LoadErr%
   GOTO Fcleanup2
END IF

PRINT "SegBptr& = $"HEX$(SegBptr&)
SegAddr& = SegBptr& * 4
PRINT "SegAddr& = $"HEX$(SegAddr&)
InitRtn& = SegAddr& + 4
PRINT "InitRtn& = $"HEX$(InitRtn&)


REM *****
InputLoop:
INPUT "<t>ryFun or <q>uit";k$
IF k$ = "t" THEN GOSUB TryFun: GOTO InputLoop
IF k$ = "q" THEN GOTO Fcleanup
GOTO InputLoop


TryFun:
PRINT "Calling InitRtn& for address of FunctionTable"
CALL InitRtn&(VARPTR(Result&))
FunTable& = Result&
PRINT "Function table address = $"HEX$(FunTable&)

Fun1& = PEEKL(FunTable&)
Fun2& = PEEKL(FunTable& + 4)
PRINT "  Func 1 addr    = $"HEX$(Fun1&)
PRINT "  Func 2 addr    = $"HEX$(Fun2&)

INPUT "<c>ontinue or <q>uit";k$
IF k$ <> "c" THEN GOTO SkipFun:
PRINT
PRINT "Fun1 moves the screen"
INPUT "Press <RETURN> when ready";k$
delta& = 50
CALL Fun1&(VARPTR(Result&),delta&)
PRINT "Finished Fun1&"
PRINT
PRINT "Fun2 doubles an integer"
INPUT "   Enter an integer";k$
arg1& = VAL(k$)
PRINT "Argument ="arg1&
CALL Fun2&(VARPTR(Result&),arg1&)
PRINT "Result ="Result&
PRINT "Finished Fun2&"

SkipFun:
RETURN

Fcleanup:
CALL UnLoadSeg&(SegBptr&)
Fcleanup2:
LIBRARY CLOSE
PRINT "Done"  
END