4 Versionstring: $VER: example_lib.c 1.2 (21.06.2007)
7 Description: shows how the SDI_lib.h header include can be used
9 1.0 05.10.04 : initial version showing how the SDI_lib.h headers can help
10 when used for maintaining AmigaOS compatible shared library
11 interfaces upon compatible operating systems like AmigaOS3,
14 1.1 20.06.07 : moved LIBFUNC to be first in line acording to changes in
15 SDI_lib.h. (Guido Mersmann)
17 1.2 21.06.07 : added missing libvector to MorphOS/AmigaOS3 libvectors[]
20 Please note that this example is just for educational purposes and wasn't
21 checked for complete correctness. However, it should compile and probably also
22 work as expected. But please note that its purpose is to show how a shared
23 library can held platform independent over all different available AmigaOS
24 platforms like OS3, OS4 and MorphOS.
26 Feel free to comment and submit any suggestions directly to
27 Jens.Langner@light-speed.de
31 #include <exec/types.h>
32 #include <exec/libraries.h>
33 #include <exec/resident.h>
36 #include <proto/exec.h>
39 #include <exec/emulation.h>
47 #include <SDI_stdarg.h>
51 #define DATE "21.06.2007"
52 #define VERS "example.library 1.2"
53 #define VSTRING "example.library 1.2 21.06.2007)\r\n"
54 #define VERSTAG "\0$VER: example.library 1.2 (21.06.2007)"
56 static const char UserLibName
[] = "example.library";
57 static const char UserLibID
[] = "\0$VER: example.library 1.2 (21.06.2007)";
59 #if defined(__MORPHOS__)
60 struct ExecBase
*SysBase
;
63 /******************************************************************************/
64 /* >> User defineable library functions start here << */
65 /* The following section should illustrate how the SDI_lib.h macros make it */
66 /* possible to easily maintain a typical Amiga shared library interface if */
67 /* compatibility over all common (OS3/OS4, MorphOS) is required */
68 /******************************************************************************/
70 // first the prototypes of all our public library functions
71 LIBPROTO(SayHelloOS4
, char *, void);
72 LIBPROTO(SayHelloOS3
, char *, void);
73 LIBPROTO(SayHelloMOS
, char *, void);
74 LIBPROTO(Uppercase
, char *, REG(a0
, char *txt
));
75 LIBPROTOVA(SPrintf
, char *, REG(a0
, char *buf
), REG(a1
, char *format
), ...);
77 // let us now create the libvector.
78 // Please note that the start of the vectors has to be always the "LFUNC_FAS"
80 #define libvector LFUNC_FAS(SayHelloOS4) \
81 LFUNC_FA_(SayHelloOS3) \
82 LFUNC_FA_(SayHelloMOS) \
83 LFUNC_FA_(Uppercase) \
86 // then we require to generate library stubs for each library functions
87 // because OS4 comes with an additional "struct Interface*" parameter which we
88 // want to keep transparent in our code. Therefore we need to have wrapper/stub
89 // functions to call the real functions instead.
90 #if defined(__amigaos4__)
92 LIBPROTO(SayHelloOS4
, char *)
97 LIBPROTO(SayHelloOS3
, char *)
102 LIBPROTO(SayHelloMOS
, char *)
104 return SayHelloMOS();
107 LIBPROTO(Uppercase
, char *, REG(a0
, char *txt
))
109 return Uppercase(txt
);
112 LIBPROTOVA(SPrintf
, char *, REG(a0
, char *buf
), REG(a1
, char *format
), ...)
116 va_startlinear(args
, format
);
118 ret
= SPrintf(buf
, format
, va_getlinearva(args
, ULONG
));
127 // Now the real implementations of the library functions above like in
128 // a normal AmigaOS shared library follow
129 LIBFUNC
char * SayHelloOS4()
131 return "Hello AmigaOS4!!!";
134 LIBFUNC
char * SayHelloOS3()
136 return "Hello AmigaOS3!!!";
139 LIBFUNC
char * SayHelloMOS()
141 return "Hello MorphOS!!!";
144 LIBFUNC
char * Uppercase(REG(a0
, char *txt
))
157 LIBFUNC
char * STDARGS
SPrintf(REG(a0
, char *buf
), REG(a1
, char *fmt
), ...)
162 RawDoFmt(fmt
, VA_ARG(args
, void *), NULL
, buf
);
168 /******************************************************************************/
169 /* Starting from here starts the "standard" Amiga library initialization. */
170 /* All the above should have illustrated enough how "easy" it is to use the */
171 /* SDI_lib.h header file and how it can help in developing a shared library */
172 /* for multiple AmigaOS compatible platforms. */
173 /******************************************************************************/
175 /******************************************************************************/
176 /* Local Structures & Prototypes */
177 /******************************************************************************/
181 struct Library libBase
;
182 struct Library
*sysBase
;
186 #if defined(__amigaos4__)
188 LIBFUNC
static struct LibraryHeader
* LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
);
189 LIBFUNC
static BPTR
LibExpunge (struct LibraryManagerInterface
*Self
);
190 LIBFUNC
static struct LibraryHeader
* LibOpen (struct LibraryManagerInterface
*Self
, ULONG version
);
191 LIBFUNC
static BPTR
LibClose (struct LibraryManagerInterface
*Self
);
193 #elif defined(__MORPHOS__)
195 LIBFUNC
static struct LibraryHeader
* LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
);
196 LIBFUNC
static BPTR
LibExpunge(void);
197 LIBFUNC
static struct LibraryHeader
* LibOpen (void);
198 LIBFUNC
static BPTR
LibClose (void);
199 LIBFUNC
static LONG
LibNull (void);
203 LIBFUNC
static struct LibraryHeader
* LibInit (REG(a0
, BPTR Segment
), REG(d0
, struct LibraryHeader
*lh
), REG(a6
, struct ExecBase
*sb
));
204 LIBFUNC
static BPTR
LibExpunge (REG(a6
, struct LibraryHeader
*base
));
205 LIBFUNC
static struct LibraryHeader
* LibOpen (REG(a6
, struct LibraryHeader
*base
));
206 LIBFUNC
static BPTR
LibClose (REG(a6
, struct LibraryHeader
*base
));
207 LIBFUNC
static LONG
LibNull (void);
211 /******************************************************************************/
212 /* Dummy entry point and LibNull() function all in one */
213 /******************************************************************************/
215 #if defined(__amigaos4__)
224 #if !defined(__amigaos4__)
225 LIBFUNC
static LONG
LibNull(VOID
)
231 /******************************************************************************/
232 /* Local data structures */
233 /******************************************************************************/
235 #if defined(__amigaos4__)
236 /* ------------------- OS4 Manager Interface ------------------------ */
237 STATIC ULONG
LibObtain(struct LibraryManagerInterface
*Self
)
239 return(Self
->Data
.RefCount
++);
242 STATIC ULONG
LibRelease(struct LibraryManagerInterface
*Self
)
244 return(Self
->Data
.RefCount
--);
247 STATIC CONST APTR LibManagerVectors
[] =
260 STATIC CONST
struct TagItem LibManagerTags
[] =
262 {MIT_Name
, (ULONG
)"__library"},
263 {MIT_VectorTable
, (ULONG
)LibManagerVectors
},
268 /* ------------------- Library Interface(s) ------------------------ */
270 STATIC CONST APTR LibVectors
[] =
280 STATIC CONST
struct TagItem MainTags
[] =
282 {MIT_Name
, (ULONG
)"main"},
283 {MIT_VectorTable
, (ULONG
)LibVectors
},
289 STATIC CONST ULONG LibInterfaces
[] =
291 (ULONG
)LibManagerTags
,
296 /* --------------------- m68k Library stubs ------------------------ */
298 STATIC ULONG
stub_OpenPPC(ULONG
*regarray
)
300 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
301 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
302 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
304 return (ULONG
) Self
->Open(0);
306 struct EmuTrap stub_Open
= { TRAPINST
, TRAPTYPE
, stub_OpenPPC
};
308 STATIC ULONG
stub_ClosePPC(ULONG
*regarray
)
310 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
311 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
312 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
314 return (ULONG
) Self
->Close();
316 struct EmuTrap stub_Close
= { TRAPINST
, TRAPTYPE
, stub_ClosePPC
};
318 STATIC ULONG
stub_ExpungePPC(ULONG
*regarray
)
322 struct EmuTrap stub_Expunge
= { TRAPINST
, TRAPTYPE
, stub_ExpungePPC
};
324 STATIC ULONG
stub_ReservedPPC(ULONG
*regarray
)
328 struct EmuTrap stub_Reserved
= { TRAPINST
, TRAPTYPE
, stub_ReservedPPC
};
330 STATIC ULONG VecTable68K
[] =
334 (ULONG
)&stub_Expunge
,
335 (ULONG
)&stub_Reserved
,
339 /* ----------------------- LibCreate Tags -------------------------- */
341 STATIC CONST
struct TagItem LibCreateTags
[] =
343 {CLT_DataSize
, (ULONG
)(sizeof(struct LibraryHeader
))},
344 {CLT_InitFunc
, (ULONG
)LibInit
},
345 {CLT_Interfaces
, (ULONG
)LibInterfaces
},
346 {CLT_Vector68K
, (ULONG
)VecTable68K
},
352 STATIC CONST APTR LibVectors
[] =
355 (APTR
)FUNCARRAY_32BIT_NATIVE
,
365 STATIC CONST ULONG LibInitTab
[] =
367 sizeof(struct LibraryHeader
),
375 /* ------------------- ROM Tag ------------------------ */
376 static const USED_VAR
struct Resident ROMTag
=
379 (struct Resident
*)&ROMTag
,
380 (struct Resident
*)&ROMTag
+ 1,
381 #if defined(__amigaos4__)
382 RTF_AUTOINIT
|RTF_NATIVE
, // The Library should be set up according to the given table.
383 #elif defined(__MORPHOS__)
384 RTF_AUTOINIT
|RTF_PPC
,
393 #if defined(__amigaos4__)
394 (APTR
)LibCreateTags
// This table is for initializing the Library.
400 #if defined(__MORPHOS__)
402 * To tell the loader that this is a new emulppc elf and not
403 * one for the ppc.library.
406 ULONG USED_VAR __amigappc__
=1;
407 ULONG USED_VAR __abox__
=1;
409 #endif /* __MORPHOS */
411 /******************************************************************************/
412 /* Standard Library Functions, all of them are called in Forbid() state. */
413 /******************************************************************************/
416 #define DeleteLibrary(LIB) \
417 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
420 #if defined(__amigaos4__)
421 static struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
)
423 struct ExecBase
*sb
= (struct ExecBase
*)pIExec
->Data
.LibBase
;
425 #elif defined(__MORPHOS__)
426 static struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
)
429 LIBFUNC
static struct LibraryHeader
* LibInit(REG(a0
, BPTR librarySegment
), REG(d0
, struct LibraryHeader
*base
), REG(a6
, struct ExecBase
*sb
))
435 base
->libBase
.lib_Node
.ln_Type
= NT_LIBRARY
;
436 base
->libBase
.lib_Node
.ln_Pri
= 0;
437 base
->libBase
.lib_Node
.ln_Name
= (char *)UserLibName
;
438 base
->libBase
.lib_Flags
= LIBF_CHANGED
| LIBF_SUMUSED
;
439 base
->libBase
.lib_Version
= VERSION
;
440 base
->libBase
.lib_Revision
= REVISION
;
441 base
->libBase
.lib_IdString
= (char *)UserLibID
;
443 base
->segList
= librarySegment
;
444 base
->sysBase
= (APTR
)SysBase
;
449 #if defined(__amigaos4__)
450 static BPTR
LibExpunge(struct LibraryManagerInterface
*Self
)
452 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
453 #elif defined(__MORPHOS__)
454 static BPTR
LibExpunge(void)
456 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
458 LIBFUNC
static BPTR
LibExpunge(REG(a6
, struct LibraryHeader
*base
))
463 if(base
->libBase
.lib_OpenCnt
> 0)
465 base
->libBase
.lib_Flags
|= LIBF_DELEXP
;
469 SysBase
= (APTR
)base
->sysBase
;
472 Remove((struct Node
*)base
);
473 DeleteLibrary(&base
->libBase
);
478 #if defined(__amigaos4__)
479 static struct LibraryHeader
*LibOpen(struct LibraryManagerInterface
*Self
, ULONG version
)
481 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
482 #elif defined(__MORPHOS__)
483 static struct LibraryHeader
*LibOpen(void)
485 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
487 LIBFUNC
static struct LibraryHeader
* LibOpen(REG(a6
, struct LibraryHeader
*base
))
491 base
->libBase
.lib_Flags
&= ~LIBF_DELEXP
;
492 base
->libBase
.lib_OpenCnt
++;
497 #if defined(__amigaos4__)
498 static BPTR
LibClose(struct LibraryManagerInterface
*Self
)
500 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
501 #elif defined(__MORPHOS__)
502 static BPTR
LibClose(void)
504 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
506 LIBFUNC
static BPTR
LibClose(REG(a6
, struct LibraryHeader
*base
))
510 if(base
->libBase
.lib_OpenCnt
> 0 &&
511 --base
->libBase
.lib_OpenCnt
== 0)
513 if(base
->libBase
.lib_Flags
& LIBF_DELEXP
)
515 #if defined(__amigaos4__)
516 return LibExpunge(Self
);
517 #elif defined(__MORPHOS__)
520 return LibExpunge(base
);