【ARM】重新定义低级库函数,以便能够直接使用 C 库中的高级库函数
Redefining low-level library functions to enable direct use of high-level library functions in the C library
If you define your own version of __FILE
, your own fputc()
and ferror()
functions, and the __stdout
object, you can use all of the printf()
family, fwrite()
, fputs()
, puts() and
the C++ object std::cout
unchanged from the library.
These examples show you how to do this. However, consider modifying the system I/O functions instead of these low-level library functions if you require real file handling.
You are not required to re-implement every function shown in these examples. Only re-implement the functions that are used in your application.
Retargeting printf()
#include <stdio.h>
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef'd in stdio.h. */
FILE __stdout;
int fputc(int ch, FILE *f)
{
/* Your implementation of fputc(). */
return ch;
}
int ferror(FILE *f)
{
/* Your implementation of ferror(). */
return 0;
}
void test(void)
{
printf("Hello world\n");
}
Note
Be aware of endianness with
fputc()
.fputc()
takes anint
parameter, but contains only a character. Whether the character is in the first or the last byte of the integer variable depends on the endianness. The following code sample avoids problems with endianness:extern void sendchar(char *ch); int fputc(int ch, FILE *f) { /* example: write a character to an LCD */ char tempch = ch; // temp char avoids endianness issue sendchar(&tempch); // sendchar(&ch) would not work everywhere return ch; }
Retargeting cout
File 1: Re-implement any functions that require re-implementation.
#include <stdio.h>
namespace std {
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
FILE __stdout;
FILE __stdin;
FILE __stderr;
int fgetc(FILE *f)
{
/* Your implementation of fgetc(). */
return 0;
}
int fputc(int c, FILE *stream)
{
/* Your implementation of fputc(). */
}
int ferror(FILE *stream)
{
/* Your implementation of ferror(). */
}
long int ftell(FILE *stream)
{
/* Your implementation of ftell(). */
}
int fclose(FILE *f)
{
/* Your implementation of fclose(). */
return 0;
}
int fseek(FILE *f, long nPos, int nMode)
{
/* Your implementation of fseek(). */
return 0;
}
int fflush(FILE *f)
{
/* Your implementation of fflush(). */
return 0;
}
}
File 2: Print "Hello world" using your re-implemented functions.
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world\n";
return 0;
}
By default, fread()
and fwrite()
call fast block input/output functions that are part of the Arm® stream implementation. If you define your own __FILE
structure instead of using the Arm stream implementation, fread()
and fwrite()
call fgetc()
instead of calling the block input/output functions.
【来源】