void pointer casting

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • void pointer casting

      Hey Guys,

      So I am working on converting my engine to a library to simplify the process of making new games, and hopefully to use it to hook into a Game Editor as done in the book.

      I found I had to do alot of changes, especially adding alot of abstract interfaces as base classes, this allows me to be able to completely seperate a game project from the 3rd parts librarys, otherwise they will be trying to include things like tinyXML, Zlib, etc.

      I have run into some cases though for instance in my IActorComponent, where it uses TinyXML and in the VInit function uses a TiXmlElement pointer, this won't do as my desire is to keep the user from having to lug around the 3rd party lib's.

      I chose to use a void pointer, everything works fine and I cast to a TiXmlElement pointer on the source file side, I just wanted to run this by someone else to be sure I am not doing something unsafe.

      To my knowledge, using void pointers is OK as long as you are vigilant at not passing the wrong type in.
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • RE: void pointer casting

      Using void pointers is, by definition, an unsafe. I've fixed a number of bugs due to unsafe casts like this. If you're careful, it may be fine. Or it may not. ;)

      -Rez
    • Ok, do you have any ideas of alternatives? Here are 2 Interface classes where I had to use void * but still felt like I should be doing it differently.

      Source Code

      1. #ifndef _IINPUTMANAGER_H_
      2. #define _IINPUTMANAGER_H_
      3. /*===========================
      4. Name: DeviceInputMsg
      5. Description:
      6. =============================*/
      7. struct DeviceInputMsg
      8. {
      9. int type;
      10. int param1;
      11. int param2;
      12. int extra1;
      13. int extra2;
      14. };
      15. /*==========================
      16. Name: IInputManager
      17. Description:
      18. ============================*/
      19. class IInputManager
      20. {
      21. public:
      22. virtual bool VInit() = 0;
      23. virtual bool VShutDown() = 0;
      24. virtual void VProcessInput(void* msg) = 0;
      25. };
      26. #endif
      Display All


      C Source Code

      1. #ifndef _IACTORCOMPONENT_H_
      2. #define _IACTORCOMPONENT_H_
      3. #include <map>
      4. #include <memory>
      5. #include <string>
      6. /*=======================
      7. Name: IActorComponent
      8. Description: Abstract Interface Class for pluggable components, which define an actor
      9. =========================*/
      10. class Actor; //Forward Declaration
      11. typedef std::shared_ptr<Actor> StrongActorPtr;
      12. typedef std::weak_ptr<Actor> WeakActorPtr;
      13. typedef std::string ComponentID;
      14. class IActorComponent
      15. {
      16. friend class CActorFactory;
      17. protected:
      18. StrongActorPtr m_pParent;
      19. public:
      20. virtual ~IActorComponent(){}
      21. virtual bool VInit(void* pData) = 0;
      22. virtual void VPostInit(){}
      23. virtual void VUpdate(){}
      24. virtual ComponentID VGetID() const = 0;
      25. private:
      26. void SetParent(StrongActorPtr pParent){ m_pParent = pParent; }
      27. };
      28. typedef std::tr1::shared_ptr<IActorComponent> StrongActorComponentPtr;
      29. typedef std::map<ComponentID, StrongActorComponentPtr > ActorComponentMap;
      30. #endif
      Display All


      Both places I had to use a void* otherwise I would have to have the header files for each 3rd party library included in the Game Logic Project.
      Any pointers (no pun intended)?
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • My suggestion would be to rethink how this interface is set up so that you can get rid of the void* pData parameter completely.

      As it is now, presumabley if we are working with XML here, then whatever is calling VInit(void* pData) must know that it is passing and TiXmlElement object, because it had to parse the TiXmlDocument, and pull out the element data.

      So in other words, it knows it is working with a component that needs XML data to parse. Therefore in your engine you provide the base interface

      Source Code

      1. class IActorComponent
      2. {
      3. VInit();
      4. // etc.
      5. };


      Then as a user, if I decide I want my actors to build components from XML data with tinyxml, I make a base class, which all my other components will inherit from:

      Source Code

      1. class XmlActorComponent : public IActorComponent
      2. {
      3. private:
      4. TiXmlElement * _data;
      5. public:
      6. XmlActorComponent(TiXmlElement * my_Data);
      7. // etc.
      8. VInit() { /* load data from _data member */ }
      9. };


      The I would probably need a custom Actor Factory that would know to pull XML files, so i'd make an XmlActorFactory that inherits from IActorFactory. And when I create components for my actors, I always initialize the component by sending in the xml element to the constructor, then call VInit().

      Then I wouldn't need the void* pData parameter at all.

      Just a thought anyway.
    • You aren't getting around including the lib in that project because in your CPP file, you still have to cast it to the appropriate type.

      There are a number of ways to get around this. One way is to write an abstraction layer where you have an abstract interface for each XML component.

      Source Code

      1. class XmlFile
      2. {
      3. public:
      4. virtual ~XmlFile(void) { }
      5. virtual bool LoadFile(const char* filename) = 0;
      6. virtual XmlNode* GetRootNode(void) = 0;
      7. };
      8. class XmlNode
      9. {
      10. public:
      11. virtual XmlNode* GetNextChild(const char* nodeName) = 0;
      12. // etc....
      13. };
      Display All


      Then you write the TinyXml implementation in whatever project you feel is appropriate.

      Source Code

      1. class TinyXmlFile : public XmlFile
      2. {
      3. TiXmlElement* m_pRoot;
      4. public:
      5. TinyXmlFile(void);
      6. virtual ~TinyXmlFile(void);
      7. virtual bool LoadFile(const char* filename);
      8. virtual XmlNode* GetRootNode(void);
      9. };
      10. class TinyXmlNode : public XmlNode
      11. {
      12. public:
      13. virtual XmlNode* GetNextChild(const char* nodeName) = 0;
      14. // etc....
      15. };
      Display All


      These objects are created with a factory, similar to how to the ActorComponent objects are created. Nothing outside of your TinyXml implementation files is allowed to include TinyXml files or reference TinyXml objects. You only pass around pointers to the abstract base types.

      One cool thing about this is that you can ditch TinyXml completely and replace it with something else. You would have to do anything except write some new implementation classes and instantiate the appropriate factory. You could even turn it into a build setting and switch seamlessly between the two with #if's. This is what many games do to switch between DirectX and OpenGL.

      The downside to this method is that you're essentially newing up twice the number of objects. For example, GetRoot() will need to instantiate the appropriate XmlNode object and return it, rather than just returning the TiXmlElement directly. You can mitigate this by crating common objects (like the root node) when the file is loaded, but you're still creating a lot of objects. This can be further mitigated by things like memory pools. In an XML system, I honestly wouldn't worry about it too much. You're already dealing with file IO and parsing large amounts of text. This is something that should only be done during load-time, so the extra overhead probably won't matter.

      When I started adding TinyXml to the Game Coding Complete codebase, I actually started writing a system just like this. I stopped when I realized that it was just obfuscating the code. I would absolutely do it in any real game engine, but GCC is meant to be a learning tool. I wasn't trying to teach you how to write an abstraction interface, I was trying to teach you how to build an actor component architecture. In retrospect, perhaps I should have built that abstraction layer.

      If you haven't done so, I would highly recommend that you pick up Design Patterns. It's a bit dry, but it talks about all of this stuff. You'll learn tons of different methods for abstracting and hiding implementation classes from the rest of the project.

      -Rez
    • Originally posted by Kl1X
      My suggestion would be to rethink how this interface is set up so that you can get rid of the void* pData parameter completely.

      As it is now, presumabley if we are working with XML here, then whatever is calling VInit(void* pData) must know that it is passing and TiXmlElement object, because it had to parse the TiXmlDocument, and pull out the element data.

      So in other words, it knows it is working with a component that needs XML data to parse. Therefore in your engine you provide the base interface

      Source Code

      1. class IActorComponent
      2. {
      3. VInit();
      4. // etc.
      5. };


      Then as a user, if I decide I want my actors to build components from XML data with tinyxml, I make a base class, which all my other components will inherit from:

      Source Code

      1. class XmlActorComponent : public IActorComponent
      2. {
      3. private:
      4. TiXmlElement * _data;
      5. public:
      6. XmlActorComponent(TiXmlElement * my_Data);
      7. // etc.
      8. VInit() { /* load data from _data member */ }
      9. };


      The I would probably need a custom Actor Factory that would know to pull XML files, so i'd make an XmlActorFactory that inherits from IActorFactory. And when I create components for my actors, I always initialize the component by sending in the xml element to the constructor, then call VInit().

      Then I wouldn't need the void* pData parameter at all.

      Just a thought anyway.


      I wouldn't do it this way because you're not really solving anything. You're building an abstraction around how actors are loaded, which is fine if you plan to have multiple different sources for your actors. In practice, you want the way that you load actors to consistent, so building this type of abstraction is promoting incorrect behavior. Furthermore, TinyXml will still need to included in the game logic and it's much harder to #if TinyXml completely out of your engine.

      Remember, make it nearly impossible for the programmer using the interface to use it incorrectly or inconsistently.

      -Rez
    • I suppose I was probably thinking about this problem in too abstract of a maner. But if, in my example, you leave the creation the XmlActorComponent class to the programmer who is using the library engine, then you've removed Tinyxml from the engine lib. Then it also gives them to opportunity to create something entirely different, such as an actor system based in LUA.

      I guess the biggest problem would be the potential for inconsistencies. If Joe Blow comes along and wants to make a Pascal based actor system along side an already existing xml system, he could. Then he's just doubled the maintenance and potential for bugs.

      Probably the thing I need to work on the most is Design Patterns, and being able to recognize where to use them.
    • My next C++ term has a focus on design patterns so I will be looking forward to that.
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • Ignore this if you're trying to not include TinyXml in your project. My interpretation of the original question was just avoiding including the headers, not the object files. If that's correct, then you can just forward declare the TinyXml classes, provided you only pass pointers of them. This way you can be type safe and avoid #include.

      James
    • Yes it's just the headers I am trying to avoid, I do use forward declares but I run into alot of problems with them, maybe I just don't know how to use the 100% properly. I always get errors for unimplemented classes even though it all seems to be in order.
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • This means you're attempting to use the class in a file that doesn't include the definition. If you're getting this in a cpp file, just add the include. If this is in a header file, you're probably either calling a function on the class (say, in an inline function) or you're instantiating and object of the class.

      -Rez