Using Newlib in a library
Using Newlib in a library
Hi,
I'm writing my first OS4 library and my current code uses some libc functions. As I'm using Newlib, gcc complains about INewlib not being defined.
My questions are:
- is it ok to use Newlib in a library ?
- apart from getting rid of it, what's the way to using Newlib in a library ? I could not find information about INewlib interface in the SDK.
TIA
I'm writing my first OS4 library and my current code uses some libc functions. As I'm using Newlib, gcc complains about INewlib not being defined.
My questions are:
- is it ok to use Newlib in a library ?
- apart from getting rid of it, what's the way to using Newlib in a library ? I could not find information about INewlib interface in the SDK.
TIA
God grant me the Serenity to accept the things I cannot change; Courage to change the things I can; and Wisdom to know the difference.
- tonyw
- AmigaOS Core Developer
- Posts: 1479
- Joined: Wed Mar 09, 2011 1:36 pm
- Location: Sydney, Australia
Re: Using Newlib in a library
Sure you can use newlib from within a library. The only problem is that the vector INewlib must be defined as global. It is common to allocate the variable and initialise it in the start() function, eg:
Of course, you should DropInterface() when you exit.
Note that on some machines like the X-1000 with its CFE, bss variables are not cleared at task initialisation. To be safe, always clear all your global variables to zero right at the start of your code.
Once you have it defined (as global, not static) in your startup code, it should be visible to all other source modules. You will find that there is a line somewhere (in one of the common headers) that says:
"extern struct Interface *INewlib" or something like that. The rest is automatic.
Code: Select all
struct Library *NewlibBase;
struct Interface *INewlib;
NewlibBase = IExec->OpenLibrary ("newlib.library", 53);
if (NewlibBase == NULL)
{
IExec->DebugPrintF("Can't open V53 newlib.library\n");
break;
}
INewlib = (struct Interface *)IExec->GetInterface (NewlibBase, "main", 1, NULL);
if (INewlib == NULL)
{
break;
}
Note that on some machines like the X-1000 with its CFE, bss variables are not cleared at task initialisation. To be safe, always clear all your global variables to zero right at the start of your code.
Once you have it defined (as global, not static) in your startup code, it should be visible to all other source modules. You will find that there is a line somewhere (in one of the common headers) that says:
"extern struct Interface *INewlib" or something like that. The rest is automatic.
cheers
tony
tony
Re: Using Newlib in a library
Thank you for your fast answer.
I'm wondering what happens when different applications open the library simutaneously. I thought global variables would be a problem. Does the library have to manage the sharing of the variable or does each process get its own global variable ?
Should that kind of global variable solution be used for all interfaces ? Until now I was storing library bases and interfaces (IExec, IIntuition ...) into my library base.
I'm wondering what happens when different applications open the library simutaneously. I thought global variables would be a problem. Does the library have to manage the sharing of the variable or does each process get its own global variable ?
Should that kind of global variable solution be used for all interfaces ? Until now I was storing library bases and interfaces (IExec, IIntuition ...) into my library base.
God grant me the Serenity to accept the things I cannot change; Courage to change the things I can; and Wisdom to know the difference.
- broadblues
- AmigaOS Core Developer
- Posts: 600
- Joined: Sat Jun 18, 2011 2:40 am
- Location: Portsmouth, UK
- Contact:
Re: Using Newlib in a library
You should open Open newlib.library and get the interface in the lib_init() and close it in lib_expunge() functions of the library.Olrick wrote:Thank you for your fast answer.
I'm wondering what happens when different applications open the library simutaneously. I thought global variables would be a problem. Does the library have to manage the sharing of the variable or does each process get its own global variable ?
In this case it does need to be a global as the clibrary calls reference that INewlib variable.
It doesn't mattter for INewlib as the context information is stored in the Process structure for each Process using the library, not in the libary interface, so it's safe to share.
Re: Using Newlib in a library
Ok, thank you both for the support.
Once my library is validated, I will contribute to the wiki.
Once my library is validated, I will contribute to the wiki.
God grant me the Serenity to accept the things I cannot change; Courage to change the things I can; and Wisdom to know the difference.
Re: Using Newlib in a library
Here is a new question:
How should I handle an error during libInit() (example: can't open another library) and abort cleanly my library opening sothat the user application get informed ?
TIA
How should I handle an error during libInit() (example: can't open another library) and abort cleanly my library opening sothat the user application get informed ?
TIA
God grant me the Serenity to accept the things I cannot change; Courage to change the things I can; and Wisdom to know the difference.
- tonyw
- AmigaOS Core Developer
- Posts: 1479
- Joined: Wed Mar 09, 2011 1:36 pm
- Location: Sydney, Australia
Re: Using Newlib in a library
You must return NULL to the caller so that she knows it failed. There is no provision for returning an error code, so any error reports must be created some other way.
The easiest way is to open DOS and make up a TimedDosRequester() with your message. For example, this code reports that a library (or a handler in this case) found an old version of DOS:
The easiest way is to open DOS and make up a TimedDosRequester() with your message. For example, this code reports that a library (or a handler in this case) found an old version of DOS:
Code: Select all
CONST TEXT youNeed[] = "You need dos.library 53.95+\nYou only have V%ld.%ld\n\n";
// This line prints a message on the serial debug output
IExec->DebugPrintF (youNeed, DOSBase->lib_Version, DOSBase->lib_Revision);
// This line makes up the requester
IDOS->TimedDosRequesterTags(
TDR_Timeout, 30,
TDR_NonBlocking, TRUE,
TDR_TitleString, VSTRING,
TDR_FormatString, youNeed,
TDR_GadgetString, "OK",
TDR_ImageType, TDRIMAGE_ERROR,
TDR_Arg1, (int32)DOSBase->lib_Version,
TDR_Arg2, (int32)DOSBase->lib_Revision,
TAG_END);
// Now clean up, exit and return NULL
cheers
tony
tony
Re: Using Newlib in a library
Thank you Tonyw
I guessed I have to return NULL, as that's what happens for any library. But my wonder is: should I clean up the LibraryBase or will libExpunge() be called automagically to do it ?
I guessed I have to return NULL, as that's what happens for any library. But my wonder is: should I clean up the LibraryBase or will libExpunge() be called automagically to do it ?
God grant me the Serenity to accept the things I cannot change; Courage to change the things I can; and Wisdom to know the difference.
- broadblues
- AmigaOS Core Developer
- Posts: 600
- Joined: Sat Jun 18, 2011 2:40 am
- Location: Portsmouth, UK
- Contact:
Re: Using Newlib in a library
If libInit() fails the library wont be loaded, so I don;t think expeunge can be called, so you must call your cleanup function.
It's a good idea to seperate your cleanup routine into a function that can be called from both libInit() on failure and libExpunge() on expunge.
It's a good idea to seperate your cleanup routine into a function that can be called from both libInit() on failure and libExpunge() on expunge.
Re: Using Newlib in a library
I was thinking about the cleaning instructions generated in libExpunge() by IDLTool:
I thought it was the cleanup of the LibraryBase I get in libInit(), was I wrong ?
And is there anything to do with the segList I get from libInit() ?
I guess these two resources got allocated and must be freed in case of failure.
Code: Select all
libBase->IExec->Remove((struct Node *)libBase);
libBase->IExec->DeleteLibrary((struct Library *)libBase);
And is there anything to do with the segList I get from libInit() ?
I guess these two resources got allocated and must be freed in case of failure.
God grant me the Serenity to accept the things I cannot change; Courage to change the things I can; and Wisdom to know the difference.