How to add ARexx interface to library?

6 posts / 0 new
Last post
jap
jap's picture
Offline
Last seen: 8 months 1 week ago
Joined: 2011-06-04 05:53
How to add ARexx interface to library?

Hello,
Are there any examples how to create a library with an ARexx function host interface with idltool?

thellier
thellier's picture
Offline
Last seen: 5 years 9 months ago
Joined: 2014-03-04 12:43
Re: How to add ARexx interface to library?

hello

static LONG stub_RexxSupportPPC(uint32 *regarray)
{
struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((uint32)Base + Base->lib_PosSize);
struct Microbe3DIFace *Self = (struct Microbe3DIFace *) ExtLib->MainIFace;
struct RexxStuff R;

R.msg=(APTR)regarray[8]; /* arexx msg in a0 */
MyRexxSupport(&R); /* use builtin function */
regarray[8]=regarray[9]=(ULONG)R.argstring; /* arexx argstring in a0 and a1 */
return(R.ret); /* arexx error-code (ret) in d0 */
}
/*=================================================================*/
ULONG rx_DoObjectFx(struct RexxMsg *m)
{
U3D_DoObjectFx((APTR)IA1,(ULONG)IA2);
return(0);
}
/*=================================================================*/
ULONG rx_AddMotionCapture(struct RexxMsg *m)
{
ULONG ret;
ret=(ULONG)U3D_AddMotionCapture((APTR)IA1,(UBYTE*)SA2,(ULONG)IA3,(ULONG)IA4,(float)FA5);
return(ret);
}
/*=================================================================*/
struct arexxfunc rxfuncs[] = {
{"REXXGETFLOAT" ,1,'F',rx_RexxGetFloat},
{"REXXGETNAME" ,1,'S',rx_RexxGetName},
{"REXXSETCOLOR" ,5,'R',rx_RexxSetColor},
{"REXXSETFLOAT" ,2,'R',rx_RexxSetFloat},
{"REXXSETNAME" ,2,'R',rx_RexxSetName},
{"REXXSETVERTEX" ,4,'R',rx_RexxSetVertex},

{"ADDBONE" ,6,'R',rx_AddBone},
{"ADDFACE" ,1,' ',rx_AddFace},
{"ADDGROUP" ,3,'R',rx_AddGroup},
{"ADDINSTANCE" ,3,'R',rx_AddInstance},
{"ADDMAP" ,6,'R',rx_AddMap},
{"ADDMOTIONCAPTURE" ,5,'R',rx_AddMotionCapture},
{"ADDOBJECT" ,4,'R',rx_AddObject},
{"ADDPOINT" ,4,' ',rx_AddPoint},
{"ADDSKIN" ,3,'R',rx_AddSkin},
{"BOX" ,4,' ',rx_Box},
{"DELETE" ,1,' ',rx_Delete},
{"DIMENSIONS" ,4,' ',rx_Dimensions},
{"DOOBJECTFX" ,2,' ',rx_DoObjectFx},
{"DRAWSCENE" ,1,' ',rx_DrawScene},
{"EASYOPENSCENE" ,3,'R',rx_EasyOpenScene},
{"FIND" ,3,'R',rx_Find},
{"GET" ,3,'R',rx_Get},
{"GETTILE" ,4,'R',rx_GetTile},
{"GRIDWELD" ,4,' ',rx_GridWeld},
{"MOTIONCAPTURECUT" ,4,'R',rx_MotionCaptureCut},
{"MOTIONCAPTUREJOIN" ,4,'R',rx_MotionCaptureJoin},
{"MOTIONCAPTUREFX" ,5,'R',rx_MotionCaptureFx},
{"NAME" ,1,'R',rx_Name},
{"NORMALS" ,2,' ',rx_Normals},
{"OPENSCENE" ,7,'R',rx_OpenScene},
{"QUERYVALUE" ,2,'R',rx_QueryValue},
{"READ" ,2,'R',rx_Read},
{"REVERSEWINDING" ,1,' ',rx_ReverseWinding},
{"ROTATE" ,5,' ',rx_Rotate},
{"SCALE" ,5,' ',rx_Scale},
{"SETAMPLITUDE" ,7,' ',rx_SetAmplitude},
{"SETBONEEQUIVALENCE" ,3,' ',rx_SetBoneEquivalence},
{"SETBONEINFLUENCE" ,4,' ',rx_SetBoneInfluence},
{"SETINSTANCE" ,3,' ',rx_SetInstance},
{"SETLIGHT" ,3,' ',rx_SetLight},
{"SETLIGHTPLUS" ,6,' ',rx_SetLightPlus},
{"SETMOTIONCAPTURE" ,3,' ',rx_SetMotionCapture},
{"SETSPECIALMATERIAL" ,4,' ',rx_SetSpecialMaterial},
{"SETTILE" ,5,' ',rx_SetTile},
{"SETTILEDEF" ,3,' ',rx_SetTileDef},
{"SETVALUE" ,3,' ',rx_SetValue},
{"SWAPAXIS" ,2,' ',rx_SwapAxis},
{"TRANSLATE" ,5,' ',rx_Translate},
{"UNITIZE" ,2,' ',rx_Unitize},
{"WELD" ,4,' ',rx_Weld},
{"WRITE" ,2,' ',rx_Write},
};
#define FUNCCOUNT (sizeof(rxfuncs)/sizeof(struct arexxfunc))
/*=================================================================*/
APTR findrxfunc(UBYTE *name)
{
ULONG n;

name=&name[4]; /* skip U3D_ */
NLOOP(FUNCCOUNT)
if(IsKeyword(rxfuncs[n].name,name))
return(&rxfuncs[n]);

return(NULL);
}
/*=================================================================*/
void MyRexxSupport(struct RexxStuff *R)
{
struct RexxMsg *m=R->msg;
struct arexxfunc *rxfunc;
UBYTE argscount;
char name[256];
ULONG n;
float *F;
struct Task *mytask;
ULONG mystack;

REM(RexxSupport)

mytask=FindTask(NULL);
mystack=((ULONG)mytask->tc_SPUpper) - ((ULONG)mytask->tc_SPLower);
if(mystack < MICROBE3DSTACK)
{
errorprintf("Error: Rexx/Stack too low %ld !!\n",mystack);
R->ret=ERR10_003; /* no memory available */
R->argstring= NULL;
((struct RxsLib*)RexxSysBase)->rl_StackSize=MICROBE3DSTACK;
return;
}

if(rexxdebug) Libprintf("RexxSupport=======================\n");
argscount = m->rm_Action & RXARGMASK;
if(rexxdebug) Libprintf("Func: %s\n",m->rm_Args[0]);
rxfunc = findrxfunc(RXARG0);

NLOOP(argscount)
{
if(rexxdebug) Libprintf("Arg%ld: <%s>\n",n+1,m->rm_Args[n+1]);
}

if (rxfunc == NULL)
{
if(rexxdebug) Libprintf("Unknown function%s !!\n",RXARG0);
R->ret=ERR10_015; /* function not found */
R->argstring= NULL;
return;
}

if (argscount != rxfunc->argscount)
{
if(rexxdebug) Libprintf("Function %s need %ld args !!\n",RXARG0,rxfunc->argscount);
R->ret=ERR10_017; /* wrong number of arguments */
R->argstring= NULL;
return;
}

if(rexxdebug==2) OSAlert("Ready?");

R->ret = rxfunc->func(m); /* call the function */
R->argstring = NULL;

if(rexxdebug) Libprintf("Function %s()\n",RXARG0);
if(rxfunc->returntype==' ') /* no return value */
{
if(rexxdebug) Libprintf("return: nothing \n");
Libsprintf(name,"0");
}

if(rxfunc->returntype=='R') /* got a return value */
{
if(rexxdebug) Libprintf("return: int \n");
Libsprintf(name,"%ld",R->ret);
}

if(rxfunc->returntype=='S') /* STRING return value */
{
if(rexxdebug) Libprintf("return: string \n");
Libsprintf(name,"%s",(UBYTE*)R->ret);
}

if(rxfunc->returntype=='F') /* float return value */
{
if(rexxdebug) Libprintf("return: float \n");
F=(float*)&R->ret; /* float encoded as LONG */
spf(name,F[0]);
}

R->ret=RC_OK;
R->argstring=CreateArgstring(name,Libstrlen(name));

if(rexxdebug) Libprintf("ret: %ld argstring: <%s>\n",R->ret,R->argstring);
if(rexxdebug) Libprintf("----------------------------------\n");
if(rexxdebug==2) OSAlert("Done");

}

Alain Thellier - Wazp3D

jap
jap's picture
Offline
Last seen: 8 months 1 week ago
Joined: 2011-06-04 05:53
Re: How to add ARexx interface to library?

Thanks! To sum it up, I can see that you have 5 functions there

  • stub_RexxSupportPPC
  • rx_DoObjectFx
  • rx_AddMotionCapture
  • findrxfunc
  • MyRexxSupport

and the supported ARexx functions are in the "rxfuncs" array. You have included two of the functions in the source code: rx_DoObjectFx() (ARexx function name DOOBJECTFX) and rx_AddMotionCapture() (ARexx function name ADDMOTIONCAPTURE).

MyRexxSupport() and findrxfunc() functions seem to be auxilliary functions and stub_RexxSupportPPC() handles all the ARexx function calls, being the ARexx function interface.

If I generate a library template with IDLTool using the following XML file,

  1. <?xml version="1.0" encoding="iso-8859-1"?>
  2. <!DOCTYPE library SYSTEM "library.dtd">
  3. <library name="mylibary" basename="MyLibraryBase" openname="mylibrary.library">
  4. <!-- Includes -->
  5. <include>exec/types.h</include>
  6. <include>mylibrary/mylibrary.h</include>
  7.  
  8. <!-- Interface definition -->
  9. <interface name="main" version="1.0" struct="MyLibraryIFace" prefix="_mylibrary_" asmprefix="IMyLibrary" global="IMyLibrary">
  10. <!-- Standard methods -->
  11. <method name="Obtain" result="uint32"/>
  12. <method name="Release" result="uint32"/>
  13. <method name="Expunge" result="void" status="unimplemented"/>
  14. <method name="Clone" result="struct MyLibraryIFace *"/>
  15.  
  16. <!-- ARexx interface -->
  17. <method name="stub_RexxSupportPPC" result="LONG">
  18. <arg name="regarray" type="uint32 *"/>
  19. </method>
  20. </interface>
  21. </library>

how do I know which offset value should be used in the ARexx ADDLIB() function call? How do you calculate it? The offset value is usually -30 and the ADDLIB() call would be something like ADDLIB( "mylibrary.library", 0, -30, 0 ), but is it -30 in this case?

thellier
thellier's picture
Offline
Last seen: 5 years 9 months ago
Joined: 2014-03-04 12:43
Re: How to add ARexx interface to library?

In fact arexx only call as a 68k program
To generate all the stuff for a.library the simpler is to start from an .sfd file thta is used for 68k .library
So put only that in (say) mylib.sfd :

==id $Id: Microbe3D_lib.sfd,v 1.0 2012/10/12 13:30:00 noname Exp $
==base _Microbe3DBase
==basetype struct Library *
==libname Microbe3D.library
==bias 30
==public
==include

LONG RexxSupport(APTR msg,APTR RexxSupportBase) (a0,a1)

then run
fdtrans mylib.sfd --all
idltool mylib.xml --all

It will generat all the needed files

Also this part will explain how to recover arguments from arexx

/*=================================================================*/
struct arexxfunc {
char *name;
UWORD argscount,returntype;
ULONG (*func)(struct RexxMsg *);
};
/*==========================================================================*/
ULONG myatoi2(UBYTE *param) /* convert string & keywords to numeric*/
{
UBYTE param2[20];
ULONG value;

if(param[0]=='U') /* convert keywords like U3D_VANILLAKEY, U3D_FPS, etc... to numeric*/
if(param[1]=='3')
if(param[2]=='D')
if(param[3]=='_')
{
value=FindKeyWord(param);
if(value==0)
{
errorprintf("Error: Unknown parameter <%s>\n",param);
return(0);
}
if(rexxdebug) Libprintf("REXX:\tKnown parameter %s : %ld\n",param,value);
Libsprintf(param2,"%ld",value); /* new param2 will contain converted keyword as numeric-string */
return(myatoi(param2));
}
return(myatoi(param));
}
/*=================================================================*/
#define RXARG0 m->rm_Args[0]
#define RXARG1 m->rm_Args[1]
#define RXARG2 m->rm_Args[2]
#define RXARG3 m->rm_Args[3]
#define RXARG4 m->rm_Args[4]
#define RXARG5 m->rm_Args[5]
#define RXARG6 m->rm_Args[6]
#define RXARG7 m->rm_Args[7]
#define RXARG8 m->rm_Args[8]
/* arg as int */
#define IA1 myatoi2(RXARG1)
#define IA2 myatoi2(RXARG2)
#define IA3 myatoi2(RXARG3)
#define IA4 myatoi2(RXARG4)
#define IA5 myatoi2(RXARG5)
#define IA6 myatoi2(RXARG6)
#define IA7 myatoi2(RXARG7)
#define IA8 myatoi2(RXARG8)
/* arg as float */
#define FA1 myatof(RXARG1)
#define FA2 myatof(RXARG2)
#define FA3 myatof(RXARG3)
#define FA4 myatof(RXARG4)
#define FA5 myatof(RXARG5)
#define FA6 myatof(RXARG6)
#define FA7 myatof(RXARG7)
#define FA8 myatof(RXARG8)
/* arg as string */
#define SA1 RXARG1
#define SA2 RXARG2
#define SA3 RXARG3
#define SA4 RXARG4
#define SA5 RXARG5
#define SA6 RXARG6
#define SA7 RXARG7
#define SA8 RXARG8

BTW all this code come from my Microbe3D sources
see arexx calling microbe3d here:
http://aminet.net/package/util/libs/Microbe3D

Alain Thellier - Wazp3D

broadblues
broadblues's picture
Offline
Last seen: 4 years 8 months ago
Joined: 2012-05-02 21:48
Re: How to add ARexx interface to library?

@thellier

In fact arexx only call as a 68k program

You should *NOT* write your library by assuming this!

If you do so and ARexx gets ported to PPC then your library will cease to function.

Taking dataypes library as an example the xml required to define the Rwexx dispatcher is like so:

  1. <method name="RLDispatch" result="LONG" status="private">
  2. <arg name="rmsg" type="struct RexxMsg *"/>
  3. <arg name="result" type="STRPTR *"/>
  4. </method>

Note it has one more arg than the 68k style dispatcher as the 68k version returns results on a0

You will need to generate the 68k stubs for the library but the one generated for the RLDispatcher function will need editing to pur the pointer resultstring A0 (regarrys[8]) .

@thellier

BYW can you put your code in '[' code ']' blocks, it;s breaking the forum layout!

broadblues
broadblues's picture
Offline
Last seen: 4 years 8 months ago
Joined: 2012-05-02 21:48
Re: How to add ARexx interface to library?

how do I know which offset value should be used in the ARexx ADDLIB() function call? How do you calculate it? The offset value is usually -30 and the ADDLIB() call would be something like ADDLIB( "mylibrary.library", 0, -30, 0 ), but is it -30 in this case?

If it's the first function after stanadrd inetrfaces ones then the offset will indeed be -30.

Make sure you use the xml I posted above (use the function name you prefer but make sure it's consistant throughout

Possible stub code

  1. static LONG stub_RLDispatchPPC(ULONG *regarray)
  2. {
  3. /* standard preamble as generated by IDLTool */
  4.  
  5. struct Library *Base = (struct Library *) regarray[REG68K_A6/4];
  6. struct ExtendedLibrary *ExtLib = (struct ExtendedLibrary *) ((ULONG)Base + Base->lib_PosSize);
  7. struct DataTypesIFace *Self = (struct DataTypesIFace *) ExtLib->MainIFace;
  8.  
  9. /* extra veraiables to handle passing the result pointer in A0 */
  10. STRPTR resultstring;
  11. ULONG result;
  12.  
  13.  
  14. result = Self->RLDispatch(
  15. (struct RexxMsg *)regarray[8],
  16. &resultstring
  17. );
  18.  
  19. /* Now put put the result string into A0 */
  20. regarray[8] = (ULONG)resultstring;
  21. return result;
  22. }
  23.  
  24. STATIC CONST struct EmuTrap stub_RLDispatch = { TRAPINST, TRAPTYPE, (ULONG (*)(ULONG *))stub_RLDispatchPPC };
Log in or register to post comments