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