Questions regarding string messages in a C++ game

Started by
6 comments, last by Chris81 18 years, 9 months ago
Hello, How do you implement string messages for your game in C++? What I mean is for stuff like, log->Error("Something: %f", m_fSomething), or renderer->DrawText( 0, 0, "FPS: %f", m_fFPS) ?? If you use variable argument lists, you have to use vsprintf, right? Which introduces the explicit buffer size problem that the C++ way of using string streams avoids. Now, I don't have a problem using variable argument lists, even if it is mixing C in. However, I ran across a problem. I have an exported engine class from my engine dll. The class has engine->DrawText like mentioned above, which then passes to the renderer->DrawText. When I use the variable argument lists inside the client application, it works fine. When I use the exported DLL function, I get bad memory pointer problems. Any ideas? Thanks.
Advertisement
You can turn your logger/whatever into a iostream of some kind (I've done this but it can be tricky, and possibly more work than is worth it).
I do something which most programmers would frown at.

You should probably look into boost::format. It allows for that sort of printf-style formatting, and is probably plays nicer in DLL's.
I'll second the Boost.Format approach, especially since it doesn't force other people to use it -- it just means accepting a std::string instead of a char const *, so they can build that std::string any way they want.

( Boost.Format is a particularly convenient way, however :P )
Heheh, I found an alternate solution to what the rest of the people here are saying [smile]

Basically, my LogMessage function takes a string as it's message parameter. Now, that's all well and good, but you still have that problem of not being able to string together variables and strings. So I simply defined a few global operators, ie. string & operator + (string & source, int dest) etc, so now I just use the + operator to string together any variables I want, provided there's some string in there somewhere. Regrettably, this method doeshave some downsides, one of them being that I have to pay attention to the order I have the variables in, and sometimes switch things around. But other then that litte thing, it works like a charm!
Free speech for the living, dead men tell no tales,Your laughing finger will never point again...Omerta!Sing for me now!
Don't reinvent the wheel - at least not completely; take advantage of std::stringstreams (in header <sstream>).

Example (not tested):

#include <iostream>#include <sstream>class Message {  std::stringstream buffer;  public:  Message() {} // just initialize the buffer  template <typename T>  Message(const T& first) { (*this)(first); }  template <typename T>  Message& operator() (const T& next) { buffer << next; }  void operator() () { std::cout << buffer.str() << std::endl; }  // or pass "*this" to a Logger object/module, or something... whatever  // And of course you could do operator+ instead, or operator<<...  // In boolean context, check if the message is non-empty.  // There is probably a better way to do this.  operator bool() { return buffer.str().length(); }}// Examples of useif (Message extra_info = something_wrong()) {  Message("oh noes! Foo is ")(foo)(" but should be ")(bar)("!")();  extra_info();}
Thanks for all the ideas! I think I will definitely do away with variable argument lists in favor of one of these approaches. Mainly because of the DLL issue.
I have implemented the boost::format and it works great, however I get 13 conversion warnings, mostly in alt_sstream_impl.hpp.

Any ideas? Thanks.

This topic is closed to new replies.

Advertisement