09-08-2009 07:13 AM
dummy_decoy wrote:i just tested with CVI 9.0: freopen fails miserably when provided with a NULL filename.
FATAL RUN-TIME ERROR: "main.c", line 12, col 21, thread id 0x000000B8: Null pointer argument to library function.
so, you may be screwed... unless you roll your own stream functions targeting your OS, taking into account all those peculiarities. it is not difficult, only cumbersome.
i always thought the so-called STREAM functions of the C runtime where badly specified and particularly impossible to extend, that's why i use my own layer on top of those functions, which allows me to create pseudo-streams targeting whatever i want (a console, a text control in a window, a file, a socket, a com port...).
That's interesting! Could you add some informations about that separate layer: I am curious about it as it could help me to clarify some doubt of mine.
09-08-2009 09:11 AM
basically, it is an object oriented layer greatly inspired from the stream library of the Ada programming language (the best i have ever seen).
i define a STREAM as an opaque pointer type. on an object of type STREAM, 3 operations are defined: read, write and destroy. each operation return an error code, function outputs are through pass-by-reference arguments.
typedef struct STREAM STREAM;
typedef unsigned char STREAM_ELEMENT;
typedef unsigned int STREAM_ELEMENT_OFFSET;
typedef unsigned int STREAM_ELEMENT_COUNT;
// int stream_create( STREAM **stream ); // to be defined for each specific kind of stream, allocates the necessary memory.
int stream_destroy( STREAM **stream ); // free allocated resources and nulls the pointer to prevent future use
int stream_read( STREAM *stream, STREAM_ELEMENT_COUNT buffer_size, STREAM_ELEMENT buffer[], STREAM_ELEMENT_COUNT *elements_read );
int stream_write( STREAM *stream, STREAM_ELEMENT_COUNT buffer_size, STREAM_ELEMENT buffer[], STREAM_ELEMENT_COUNT *elements_written );
now, i use a clever trick to implement polymorphism and dispatching on top of that type, and i specialize a STREAM type for each kind of stream i need. the constructor is specific for each type to accomodate for configuration parameters. this allows to create (almost) any type of stream you can think of, and make streams interchangeable. any type of stream may be replaced by any other type of stream: the functions have a well defined behavior, the contract is clearly specified. each type is also free to define its own set of specialized functions, like timeout settings for com port streams for example which are not valid for other stream types.
the down-side of this approach are:
- it is the lowest common denominator for stream types. fancier stuffs do not fit here.
- you have to use this stream library from the beginning of your project, and it is not compatible with the standard streams defined for the C runtime.
- obviously, i traded design for performance, with useless function calls: type integrity checks at each call and dispatching are a bit heavy, but it is not noticeable and that's reasonable for the use i have of this library.
this may not be the ultimate solution but it proved very useful on numerous project. this kind of code layering saved me from rewriting a whole application once, when i had to switch from the CVI rs232 library to the Windows com port functions. i was also able (with the help of a well defined protocol) to extend a product with a new transport medium with very few changes. now, i can also propose multiple log output (window+file+stderr) on every of our product which uses this library, this necessitated only to write a specific stream to duplicate output to multiple streams.
(i can tell you a lot more on polymorphism or dispatching, but i am not sure it will fit here... if you are interrested, just ask)
additionally, you will notice that it separates input/output from representation: data representation does not fall in the scope of the library. that means, no fancy-schmancy stream modifiers ala C++. do you remember "cout << hex << i;"? have you ever tried to implement your own c++ stream or your own output modifier ? i tried, and now i hate c++ streams...
09-08-2009 10:04 PM
Thanks. I'll probably take the chance and just leave my dummy routine in while I develop the conversion to Studio and C++. It would be nice though if NI would bring their implementaion up to what seems to be the standard, where freopen just changes the mode of the current file if supplied with a NULL string or implement setmode.
Your implementation of streams looks interesting but adding it to the gSOAP interface would be too much.
09-09-2009 12:03 AM
@dummy_decoy: your abstract layer looks full and functional, but I can imagine you swet your guts out to have it working correctly
Anyway I am tagging your post as I want to keep this design at hand for future reference in some problems of mine.
I would like to know something more on ploymorphism but I suppose we are running off topic with this: maybe you can e-mail me something about it.
And no, I never tried such horrible things on C++
: every time I approach cpp code I get frustrated as I cannot understand a good part of the statements in here.
I'm a self-made C programmer so I imagine I'm missing some conceptual framework that would help me approaching that language.