Less juggling between string, stringstream, and char* ?

Started by
11 comments, last by moeron 16 years, 11 months ago
Quote:Original post by Domarius
To answer your question, the hge variable (m_hge in my class) is a singleton.


Oh.

The best "wrapping" might then not use any objects at all, then. Instead, you would create a namespace with free functions for all the functionality you want to "reflect", and just call hgeCreate (and use the result) from within the free functions (presumably this function will return early when the singleton already exists :) ). This is actually likely to save you significant amounts of memory (in the form of redundant pointers to the singleton that are no longer stored all over the place).

Quote:and it returns a pointer to the same object, and (AFAIK) increments a counter. When you're done with it, you call
m_hge->Release();
and it decrements the counter, and finally destroys the object when there are no more pointers to it.


Oh. That complicates things, then. But there's hope. Something like this should do it:

HGEWrapper.h:
#ifndef HGE_WRAPPER_H#define HGE_WRAPPER_Hnamespace my_hge {  void foo();}#endif


HGEWrapper.cpp:
namespace my_hge {  namespace detail {    // We define an object that uses RAII to control a pointer to the singleton:    class HGEWrapper {      HGEInterface* ptr;      // Stubbing these out prevents the object from being copied, which is      // what we want, here.      HGEWrapper(const HGEWrapper&); // don't try to implement this.      HGEWrapper& operator=(const HGEWrapper&); // don't try to implement this.      public:      HGEWrapper(int version) : ptr(HGECreate(version)) {}      ~HGEWrapper() { ptr->Release(); }      HGEInterface& operator*() { return *ptr; }      HGEInterface* operator->() { return ptr; }    } implementation;    // This ^^^ instance of the wrapper object ensures that the counter is at     // least 1 during the entire program, so that the thing won't be re-created    // continually. Note that you might have to worry about the "static order     // of initialization fiasco" here, if you're unlucky enough that there are     // other singletons in the program and they have dependencies on each other.  }  void foo() {    // Because we had to make that static instance, we just use it in the    // function implementations - although we could also create our own local    // instances and everything would be just fine.    // Anyway, we just forward things to the singleton like this:    detail::implementation->foo();  }}




On the other hand, it sort of depends on the scope of HGE. If it tries to do too much, there may be cause to split the functionality up into several headers; and there might yet be some use for actual objects (of the sort that can be freely instantiated) - e.g. to store parameters for a later call to a complicated function.
Advertisement
Well we never use "new" to create a hge object. We just go
#include "hge.h"
HGE *hge = hgeCreate(HGE_VERSION);

and hge is now loaded with a hge object.

Is there any reason why my wrapper couldn't just have a hgeCreate function that just goes

HGE myHgeCreate(whatever)
{
return hgeCreate(HGE_VERSION);
}

I would ask on the hge forums, and I have, but with no response, and you seemed to think it would complicate things, so I'm curious as to why :)

For local multiplayer retro themed games, visit Domarius Games.

google "RAII" - it stands for Resource Acquisition is Initialization. Its a long name for saying "grab resources in constructors - release them in destructors". By doing this you are more exception-safe. If you wrap those calls up in the constructor/destructor then your interface is acquired automatically whenever you instantiate an object - and it is released properly automatically whenever that object falls out of scope and is destroyed. If, for example, you directly call your createInterface function and then an exception is fired off you are not guaranteed to release the interface - but if that call is in your destructor it will be released as the stack unwinds and your object falls out of scope. This could also come up if you return out of a function earlier than you expect (an error condition maybe ).
moe.ron

This topic is closed to new replies.

Advertisement