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>
53 #define DATE "25.08.2014"
54 #define VERS "example.library 1.4"
55 #define VSTRING "example.library 1.4 25.08.2014)\r\n"
56 #define VERSTAG "\0$VER: example.library 1.4 25.08.2014)"
58 static const char UserLibName
[] = "example.library";
59 static const char UserLibID
[] = "\0$VER: example.library 1.4 25.08.2014)";
61 #if defined(__MORPHOS__) || defined(__AROS__)
62 struct ExecBase
*SysBase
;
65 /******************************************************************************/
66 /* >> User defineable library functions start here << */
67 /* The following section should illustrate how the SDI_lib.h macros make it */
68 /* possible to easily maintain a typical Amiga shared library interface if */
69 /* compatibility over all common (OS3/OS4, MorphOS) is required */
70 /******************************************************************************/
72 /******************************************************************************/
73 /* Local Structures & Prototypes */
74 /******************************************************************************/
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) \
87 // Now the real implementations of the library functions above like in
88 // a normal AmigaOS shared library follow
89 LIBPROTO(SayHelloOS4
, char *, REG(a6
, UNUSED __BASE_OR_IFACE
))
91 return "Hello AmigaOS4!!!";
94 LIBPROTO(SayHelloOS3
, char *, REG(a6
, UNUSED __BASE_OR_IFACE
))
96 return "Hello AmigaOS3!!!";
99 LIBPROTO(SayHelloMOS
, char *, REG(a6
, UNUSED __BASE_OR_IFACE
))
101 return "Hello MorphOS!!!";
104 LIBPROTO(Uppercase
, char *, REG(a6
, UNUSED __BASE_OR_IFACE
), REG(a0
, char *txt
))
117 LIBPROTO(SPrintfA
, char *, REG(a6
, UNUSED __BASE_OR_IFACE
), REG(a0
, char *buf
), REG(a1
, char *format
), REG(a2
, RAWARG args
))
119 RawDoFmt(format
, args
, NULL
, buf
);
124 #if defined(__amigaos4__)
125 // for AmigaOS4 varargs functions are separate entries in the interface structure and
126 // hence must be defined as separate functions
127 LIBPROTOVA(SPrintf
, char *, REG(a6
, UNUSED __BASE_OR_IFACE
), REG(a0
, char *buf
), REG(a1
, char *format
), ...)
132 VA_START(args
, format
);
133 // the SPrintf function will be call via the interface
134 ret
= SPrintfA(buf
, format
, VA_ARG(args
, ULONG
));
139 #elif defined(__MORPHOS__)
140 // define stub functions for all functions in the jump table which take the
141 // parameters from the emulated 68k registers. The parameters don't need to
142 // be specified again, because these are really functions taking no direct
143 // parameters. Only the type of the returned value is required.
144 LIBSTUB(SayHelloOS4
, char *)
146 __BASE_OR_IFACE
= (__BASE_OR_IFACE_TYPE
)REG_A6
;
147 return CALL_LFUNC_NP(SayHelloOS4
);
150 LIBSTUB(SayHelloOS3
, char *)
152 __BASE_OR_IFACE
= (__BASE_OR_IFACE_TYPE
)REG_A6
;
153 return CALL_LFUNC_NP(SayHelloOS3
);
156 LIBSTUB(SayHelloMOS
, char *)
158 __BASE_OR_IFACE
= (__BASE_OR_IFACE_TYPE
)REG_A6
;
159 return CALL_LFUNC_NP(SayHelloMOS
);
162 LIBSTUB(Uppercase
, char *)
164 __BASE_OR_IFACE
= (__BASE_OR_IFACE_TYPE
)REG_A6
;
165 return CALL_LFUNC(Uppercase
, (char *)REG_A0
);
168 LIBSTUB(SPrintfA
, char *)
170 __BASE_OR_IFACE
= (__BASE_OR_IFACE_TYPE
)REG_A6
;
171 return CALL_LFUNC(SprintfA
, (char)REG_A0
, (char *)REG_A1
, (APTR
)REG_A2
);
173 #elif defined(__AROS__)
174 // we use external file
177 /******************************************************************************/
178 /* Starting from here starts the "standard" Amiga library initialization. */
179 /* All the above should have illustrated enough how "easy" it is to use the */
180 /* SDI_lib.h header file and how it can help in developing a shared library */
181 /* for multiple AmigaOS compatible platforms. */
182 /******************************************************************************/
184 #if defined(__amigaos4__)
186 LIBFUNC
static struct LibraryHeader
* LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
);
187 LIBFUNC
static BPTR
LibExpunge (struct LibraryManagerInterface
*Self
);
188 LIBFUNC
static struct LibraryHeader
* LibOpen (struct LibraryManagerInterface
*Self
, ULONG version
);
189 LIBFUNC
static BPTR
LibClose (struct LibraryManagerInterface
*Self
);
191 #elif defined(__MORPHOS__)
193 LIBFUNC
static struct LibraryHeader
* LibInit (struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
);
194 LIBFUNC
static BPTR
LibExpunge(void);
195 LIBFUNC
static struct LibraryHeader
* LibOpen (void);
196 LIBFUNC
static BPTR
LibClose (void);
197 LIBFUNC
static LONG
LibNull (void);
199 #elif defined(__AROS__)
201 #include <aros/libcall.h>
203 static AROS_UFP3 (struct LibraryHeader
*, LibInit
,
204 AROS_UFPA(struct LibraryHeader
*, base
, D0
),
205 AROS_UFPA(BPTR
, librarySegment
, A0
),
206 AROS_UFPA(struct ExecBase
*, sb
, A6
)
208 static AROS_LD1 (struct LibraryHeader
*, LibOpen
,
209 AROS_LPA (UNUSED ULONG
, version
, D0
),
210 struct LibraryHeader
*, base
, 1, example
212 static AROS_LD0 (BPTR
, LibClose
,
213 struct LibraryHeader
*, base
, 2, example
215 static AROS_LD1(BPTR
, LibExpunge
,
216 AROS_LPA(UNUSED
struct LibraryHeader
*, __extrabase
, D0
),
217 struct LibraryHeader
*, base
, 3, example
222 LIBFUNC
static struct LibraryHeader
* LibInit (REG(a0
, BPTR Segment
), REG(d0
, struct LibraryHeader
*lh
), REG(a6
, struct ExecBase
*sb
));
223 LIBFUNC
static BPTR
LibExpunge (REG(a6
, struct LibraryHeader
*base
));
224 LIBFUNC
static struct LibraryHeader
* LibOpen (REG(a6
, struct LibraryHeader
*base
));
225 LIBFUNC
static BPTR
LibClose (REG(a6
, struct LibraryHeader
*base
));
226 LIBFUNC
static LONG
LibNull (void);
230 /******************************************************************************/
231 /* Dummy entry point and LibNull() function all in one */
232 /******************************************************************************/
234 #if defined(__amigaos4__)
236 #elif defined(__AROS__)
237 __startup
int Main(void)
245 #if !defined(__amigaos4__)
246 LIBFUNC
static LONG
LibNull(VOID
)
252 /******************************************************************************/
253 /* Local data structures */
254 /******************************************************************************/
256 #if defined(__amigaos4__)
257 /* ------------------- OS4 Manager Interface ------------------------ */
258 STATIC ULONG
LibObtain(struct LibraryManagerInterface
*Self
)
260 return(Self
->Data
.RefCount
++);
263 STATIC ULONG
LibRelease(struct LibraryManagerInterface
*Self
)
265 return(Self
->Data
.RefCount
--);
268 STATIC CONST APTR LibManagerVectors
[] =
281 STATIC CONST
struct TagItem LibManagerTags
[] =
283 {MIT_Name
, (ULONG
)"__library"},
284 {MIT_VectorTable
, (ULONG
)LibManagerVectors
},
289 /* ------------------- Library Interface(s) ------------------------ */
291 STATIC CONST APTR LibVectors
[] =
301 STATIC CONST
struct TagItem MainTags
[] =
303 {MIT_Name
, (ULONG
)"main"},
304 {MIT_VectorTable
, (ULONG
)LibVectors
},
310 STATIC CONST ULONG LibInterfaces
[] =
312 (ULONG
)LibManagerTags
,
317 /* --------------------- m68k Library stubs ------------------------ */
319 STATIC ULONG
stub_OpenPPC(ULONG
*regarray
)
321 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
322 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
323 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
325 return (ULONG
) Self
->Open(0);
327 struct EmuTrap stub_Open
= { TRAPINST
, TRAPTYPE
, stub_OpenPPC
};
329 STATIC ULONG
stub_ClosePPC(ULONG
*regarray
)
331 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
332 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
333 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
335 return (ULONG
) Self
->Close();
337 struct EmuTrap stub_Close
= { TRAPINST
, TRAPTYPE
, stub_ClosePPC
};
339 STATIC ULONG
stub_ExpungePPC(ULONG
*regarray
)
343 struct EmuTrap stub_Expunge
= { TRAPINST
, TRAPTYPE
, stub_ExpungePPC
};
345 STATIC ULONG
stub_ReservedPPC(ULONG
*regarray
)
349 struct EmuTrap stub_Reserved
= { TRAPINST
, TRAPTYPE
, stub_ReservedPPC
};
351 STATIC ULONG
stub_SayHelloOS4PPC(ULONG
*regarray
)
353 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
354 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
355 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
357 return (char *)Self
->SayHelloOS4();
359 struct EmuTrap stub_SayHelloOS4
= { TRAPINST
, TRAPTYPE
, stub_SayHelloOS4PPC
};
361 STATIC ULONG
stub_SayHelloOS3PPC(ULONG
*regarray
)
363 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
364 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
365 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
367 return (char *)Self
->SayHelloOS3();
369 struct EmuTrap stub_SayHelloOS3
= { TRAPINST
, TRAPTYPE
, stub_SayHelloOS3PPC
};
371 STATIC ULONG
stub_SayHelloMOSPPC(ULONG
*regarray
)
373 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
374 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
375 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
377 return (char *)Self
->SayHelloMOS();
379 struct EmuTrap stub_SayHelloMOS
= { TRAPINST
, TRAPTYPE
, stub_SayHelloMOSPPC
};
381 STATIC ULONG
stub_UppercasePPC(ULONG
*regarray
)
383 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
384 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
385 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
387 return (char *)Self
->Uppercase(
391 struct EmuTrap stub_Uppercase
= { TRAPINST
, TRAPTYPE
, stub_UppercasePPC
};
393 STATIC ULONG
stub_SPrintfAPPC(ULONG
*regarray
)
395 struct Library
*Base
= (struct Library
*) regarray
[REG68K_A6
/4];
396 struct ExtendedLibrary
*ExtLib
= (struct ExtendedLibrary
*) ((ULONG
)Base
+ Base
->lib_PosSize
);
397 struct LibraryManagerInterface
*Self
= (struct LibraryManagerInterface
*) ExtLib
->ILibrary
;
399 return (char *)Self
->SPrintfA(
405 struct EmuTrap stub_SPrintfA
= { TRAPINST
, TRAPTYPE
, stub_SPrintfAPPC
};
407 STATIC ULONG VecTable68K
[] =
411 (ULONG
)&stub_Expunge
,
412 (ULONG
)&stub_Reserved
,
413 (ULONG
)&stub_SayHelloOS4
,
414 (ULONG
)&stub_SayHelloOS3
,
415 (ULONG
)&stub_SayHelloMOS
,
416 (ULONG
)&stub_Uppercase
,
417 (ULONG
)&stub_SprintfA
,
421 /* ----------------------- LibCreate Tags -------------------------- */
423 STATIC CONST
struct TagItem LibCreateTags
[] =
425 {CLT_DataSize
, (ULONG
)(sizeof(struct LibraryHeader
))},
426 {CLT_InitFunc
, (ULONG
)LibInit
},
427 {CLT_Interfaces
, (ULONG
)LibInterfaces
},
428 {CLT_Vector68K
, (ULONG
)VecTable68K
},
434 STATIC CONST APTR LibVectors
[] =
437 (APTR
)FUNCARRAY_32BIT_NATIVE
,
439 #if defined(__AROS__)
441 AROS_SLIB_ENTRY(LibOpen
, example
, 1),
442 AROS_SLIB_ENTRY(LibClose
, example
, 2),
443 AROS_SLIB_ENTRY(LibExpunge
, example
, 3),
445 AROS_SLIB_ENTRY(LibOpen
, example
),
446 AROS_SLIB_ENTRY(LibClose
, example
),
447 AROS_SLIB_ENTRY(LibExpunge
, example
),
459 STATIC CONST IPTR LibInitTab
[] =
461 sizeof(struct LibraryHeader
),
469 /* ------------------- ROM Tag ------------------------ */
470 static const USED_VAR
struct Resident ROMTag
=
473 (struct Resident
*)&ROMTag
,
474 (struct Resident
*)&ROMTag
+ 1,
475 #if defined(__amigaos4__)
476 RTF_AUTOINIT
|RTF_NATIVE
, // The Library should be set up according to the given table.
477 #elif defined(__MORPHOS__)
478 RTF_AUTOINIT
|RTF_PPC
,
479 #elif defined(__AROS__)
480 RTF_AUTOINIT
|RTF_EXTENDED
,
489 #if defined(__amigaos4__)
490 (APTR
)LibCreateTags
// This table is for initializing the Library.
496 #if defined(__MORPHOS__)
498 * To tell the loader that this is a new emulppc elf and not
499 * one for the ppc.library.
502 ULONG USED_VAR __amigappc__
=1;
503 ULONG USED_VAR __abox__
=1;
505 #endif /* __MORPHOS */
507 /******************************************************************************/
508 /* Standard Library Functions, all of them are called in Forbid() state. */
509 /******************************************************************************/
512 #define DeleteLibrary(LIB) \
513 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
516 #if defined(__amigaos4__)
517 static struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecIFace
*pIExec
)
519 struct ExecBase
*sb
= (struct ExecBase
*)pIExec
->Data
.LibBase
;
521 #elif defined(__MORPHOS__)
522 static struct LibraryHeader
* LibInit(struct LibraryHeader
*base
, BPTR librarySegment
, struct ExecBase
*sb
)
524 #elif defined(__AROS__)
525 static AROS_UFH3(struct LibraryHeader
*, LibInit
,
526 AROS_UFHA(struct LibraryHeader
*, base
, D0
),
527 AROS_UFHA(BPTR
, librarySegment
, A0
),
528 AROS_UFHA(struct ExecBase
*, sb
, A6
)
533 LIBFUNC
static struct LibraryHeader
* LibInit(REG(a0
, BPTR librarySegment
), REG(d0
, struct LibraryHeader
*base
), REG(a6
, struct ExecBase
*sb
))
539 base
->libBase
.lib_Node
.ln_Type
= NT_LIBRARY
;
540 base
->libBase
.lib_Node
.ln_Pri
= 0;
541 base
->libBase
.lib_Node
.ln_Name
= (char *)UserLibName
;
542 base
->libBase
.lib_Flags
= LIBF_CHANGED
| LIBF_SUMUSED
;
543 base
->libBase
.lib_Version
= VERSION
;
544 base
->libBase
.lib_Revision
= REVISION
;
545 base
->libBase
.lib_IdString
= (char *)UserLibID
;
547 base
->segList
= librarySegment
;
548 base
->sysBase
= (APTR
)SysBase
;
551 #if defined(__AROS__)
556 #if defined(__amigaos4__)
557 static BPTR
LibExpunge(struct LibraryManagerInterface
*Self
)
559 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
560 #elif defined(__MORPHOS__)
561 static BPTR
LibExpunge(void)
563 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
564 #elif defined(__AROS__)
565 static AROS_LH1(BPTR
, LibExpunge
,
566 AROS_LHA(UNUSED
struct LibraryHeader
*, __extrabase
, D0
),
567 struct LibraryHeader
*, base
, 3, example
572 LIBFUNC
static BPTR
LibExpunge(REG(a6
, struct LibraryHeader
*base
))
577 if(base
->libBase
.lib_OpenCnt
> 0)
579 base
->libBase
.lib_Flags
|= LIBF_DELEXP
;
583 SysBase
= (APTR
)base
->sysBase
;
586 Remove((struct Node
*)base
);
587 DeleteLibrary(&base
->libBase
);
590 #if defined(__AROS__)
595 #if defined(__amigaos4__)
596 static struct LibraryHeader
*LibOpen(struct LibraryManagerInterface
*Self
, ULONG version
)
598 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
599 #elif defined(__MORPHOS__)
600 static struct LibraryHeader
*LibOpen(void)
602 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
603 #elif defined(__AROS__)
604 static AROS_LH1(struct LibraryHeader
*, LibOpen
,
605 AROS_LHA(UNUSED ULONG
, version
, D0
),
606 struct LibraryHeader
*, base
, 1, example
611 LIBFUNC
static struct LibraryHeader
* LibOpen(REG(a6
, struct LibraryHeader
*base
))
615 base
->libBase
.lib_Flags
&= ~LIBF_DELEXP
;
616 base
->libBase
.lib_OpenCnt
++;
619 #if defined(__AROS__)
624 #if defined(__amigaos4__)
625 static BPTR
LibClose(struct LibraryManagerInterface
*Self
)
627 struct LibraryHeader
*base
= (struct LibraryHeader
*)Self
->Data
.LibBase
;
628 #elif defined(__MORPHOS__)
629 static BPTR
LibClose(void)
631 struct LibraryHeader
*base
= (struct LibraryHeader
*)REG_A6
;
632 #elif defined(__AROS__)
633 static AROS_LH0(BPTR
, LibClose
,
634 struct LibraryHeader
*, base
, 2, example
639 LIBFUNC
static BPTR
LibClose(REG(a6
, struct LibraryHeader
*base
))
643 if(base
->libBase
.lib_OpenCnt
> 0 &&
644 --base
->libBase
.lib_OpenCnt
== 0)
646 if(base
->libBase
.lib_Flags
& LIBF_DELEXP
)
648 #if defined(__amigaos4__)
649 return LibExpunge(Self
);
650 #elif defined(__MORPHOS__)
652 #elif defined(__AROS__)
653 return AROS_LC1(BPTR
, GM_UNIQUENAME(LibExpunge
),
654 AROS_LCA(struct LibraryHeader
*, base
, D0
),
655 struct LibraryHeader
*, base
, 3, example
);
657 return LibExpunge(base
);
663 #if defined(__AROS__)