Multiple file devices in C++

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

If i use multiple filedevices ie. multiple calls to fdevopen()and store the file pointer returned by the function call. Like this:

FILE * pSerial = fdevopen(Serial::_putc, Serial::_getc);

and

FILE * pLCD = fdevopen(WireLCD::_putc, NULL);

How do I go about calling printf() for both devices?

The approach I tried, (by making my own printf function does not allow the both devices to peacefully coexist.

Any help would be appreciated.

Koen.

Assumptio mater errorum est

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

How do I go about calling printf() for both devices?

fprintf()?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok ... But that implies that both device pointers are public class members. Isn't that bad practice?

Maybe a getDevicePointer() memberfunction?

Assumptio mater errorum est

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you want to use fprintf from outside the class directly/explicitly then - yes, the devices needs to be public.

If you want to do the same from inside the class then "no".

Quote:
Maybe a getDevicePointer() memberfunction?

Close to just as bad as the public member.

If you want the class to expose a printf-like function to outside users then implement it such a function in the class and make it public. It uses the private file handle to do the job.

If you need this in several different classes them make them both inherit from a super-class with this functionality.

Now you are doing OOP!

Of-course, the alternative might be to "put the formatting functionality in the data classes" instead, and when it is formatted it is merely a simple output of a string that is needed on the different devices.

Not that you should implement it like that, but you could take a look at how C++ handles "serialization of objects" and how it combines that with streams. For inspiration. Not for implementing it all!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can of course:

stdout = &pSerial;
printf("This on serial");
stdout = &pLCD;
printf("This on LCD");

but this is no real different to:

fprintf(&pSerial, "This on Serial");
fprintf(&pLCD, "This on LCD");

if you read the example in the user manual:

http://www.nongnu.org/avr-libc/user-manual/group__stdiodemo.html

You'll see it uses a combination of both. It sets stdout to the more common device and uses printf() to that then uses fprintf() when it wants to access the other device.

You'll also see that stdio has TWO output streams as standard: stdout and stderr so yet another technique shown by the example is to have stdout pointed to UART and stderr to the LCD. You then printf() to the UArt and fprintf(stderr, ...) to the LCD.

And yes, the FILE pointers are normally global. So what? (though if you went with stdout and stderr then those are global anyway but the FILE pointers could remain hidden).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff! He is doing C++ and has OOP ambitions..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah but. I have applied modularization, encapsulation and data hiding techniques in plain C for years. Yet when it comes to an AVR I've never totally seen the point. What's to be gained by "hiding" these file pointers. Is one expecting a visit from the gremlins who are suddenly going to add a hook to main() that swap your UART and LCD pointers behind your back or something?

No doubt the computer science gurus have some strong argument for it but I have trouble seeing it.

I suppose I can see a scenario when you have two UARTs and the big question is whether stdout is currently pointing at uart0.getfilepointer() or uart1.getfilepointer()? Is that the point here?

But as long as stdout is a global shared by all how do you get round this? Don't tell me this is the whole raison d'etre for the abortion that is C++ stream << "hello" nonsense?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, I was not arguing for streams.

Even for largeish (i.e. almost large :wink:) programs, with only one developer involved (me) it has happened that the coder becomes sloppy if not following his mantras rather strictly. I have in person seen this programmer soils his code with ugly stuff.

It is totally up to the OP if he wants to make his objects serializable. Sometimes it makes sense, sometimes not.

Even when it does not make sense, and he instead chooses to have the formatting functionality in the output device classes it makes sense that he does not implement it twice but only once. Thus both the serial port driver and the LCD driver inherits from a base class with the formatting implementation, and with the actual interface to output stuff. And for that to work nicely each specific output device driver needs to have a handle, and if every driver needs it the place to keep track of it is in that base class.

I don't see this as overdoing. You all seem to see this as something that complicates things. I see it as something that simpliies things. All things in their own right places, and all that..

Apart from the hiding, perhaps more important is that the implementation can

fprintf(&my_handle, ...);

The constructors for the specific output driver classes set this member.

You could think of this as polymorphism with no vtables involved. :D

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Cliff! He is doing C++ and has OOP ambitions..

and
Quote:
Even for largeish (i.e. almost large Wink) programs, with only one developer involved (me) it has happened that the coder becomes sloppy if not following his mantras rather strictly. I have in person seen this programmer soils his code with ugly stuff.

It might be my knowlegde of the English language but these really sound like an insult.

I know perfectly well how to write a superclass and make classes inherit from them, I even know about overloading and overriding. For implementation of hardware resources that are kind a limited in "small devices" I just never saw the point. Just like Cliff never saw the point to hide data for the gremlins that might get a hook on main() in embedded applications.
Anyway, for future reference I used this approach

fprintf(RS485, "My formatstring", ...);
fprintf(LCD, "My LCD formatstring, ...);

Both classes have a public member declared in there header:

FILE * getDevicePointer(void) {return (_pFile);};

where _pFile is the private file pointer that is returned by the fdevopen() function call.
For convenience I also added a shorthand ...

operator FILE *() {return (_pFile);};

Have beer guys, this problem is solved,
KK

Assumptio mater errorum est

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

It might be my knowlegde of the English language but these really sound like an insult.

You totally misunderstood. I referred to myself. How did you miss the "me" in there?

Enjoy the beer! :D

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And... My post was in response to Cliffs. I was arguing for doing the encapsulation-and-inheritance stuff. Not against it. Nowhere did I question your abilities "write a superclass and inherit from it".

I urge you to read my posts again, and see if you can see in them that I am on the whole trying to support your stance rather than fight it or question it. E.g. "he has OO ambitions.." is an answer to Cliffs post - and trying to support what I perceived as your approach when Cliff questions it.

My next post is also an answer to the preceding post by Cliff. It tries to argue that it is not only large projects that can benefit from OO techniques. If the cost is zero or low, and the coder sees benefits - then why not?". (The next thing that will happen in that discussion is whether there are benefits. This will be a matter of opinion to a substantial degree. Therein probably lies the things that Cliff and I do not agree about - but we can handle that difference (From your "Just like Cliff never saw the point []" that you actually side with him here. That's OK.

But just a side note on what comes next:

Quote:
[...]to hide data for the gremlins that might get a hook on main() in embedded applications

In my case that gremlin is me. I am (in part) using OO techniques to protect me from myself. This was my whole point with the sentence that you so unfortunately misinterpreted.

So, have we cleared this up? I was speaking from my own experiences - being a sloppy programmer from time to time, and often having to pay for it - and arguing that good OO techniques are, uhmmm... good! In the sense that they help me avoid being sloppy.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
It might be my knowlegde of the English language
It is.