CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3

Thread: Accessing a limited struct's fields

  1. #1
    Join Date
    Mar 2012
    Posts
    1

    Accessing a limited struct's fields

    Hello guys,

    I'm an experienced coder in many languages, but not really in C/C++ even if I have now some experience, but I'm still lacking some habits.

    I'm currently working on the ioquake3 engine if some of you know about it.

    The ioquake3 engine is separated into 2 different main threads at runtime: the gamecode and the engine. Both are communicating but not all informations, and my problem resides here.

    In the gamecode, there's a struct called gentity_t which contains a lot of fields:

    Code:
    typedef struct gentity_s gentity_t;
    
    struct gentity_s {
    	entityState_t	s;				// communicated by server to clients
    	entityShared_t	r;				// shared by both the server system and game
    
    	// DO NOT MODIFY ANYTHING ABOVE THIS, THE SERVER
    	// EXPECTS THE FIELDS IN THAT ORDER!
    	//================================
    
    	struct gclient_s	*client;			// NULL if not a client
    
    	qboolean	inuse;
    
    	char		*classname;			// set in QuakeEd
    	int			spawnflags;			// set in QuakeEd
    
    	qboolean	neverFree;			// if true, FreeEntity will only unlink
    									// bodyque uses this
    
    	int			flags;				// FL_* variables
    
    	char		*model;
    	char		*model2;
    	int			freetime;			// level.time when the object was freed
    
    	int			eventTime;			// events will be cleared EVENT_VALID_MSEC after set
    	qboolean	freeAfterEvent;
    	qboolean	unlinkAfterEvent;
    
    	qboolean	physicsObject;		// if true, it can be pushed by movers and fall off edges
    									// all game items are physicsObjects,
    	float		physicsBounce;		// 1.0 = continuous bounce, 0.0 = no bounce
    	int			clipmask;			// brushes with this content value will be collided against
    									// when moving.  items and corpses do not collide against
    									// players, for instance
    
    	// movers
    	moverState_t moverState;
    	int			soundPos1;
    	int			sound1to2;
    	int			sound2to1;
    	int			soundPos2;
    	int			soundLoop;
    	gentity_t	*parent;
    	gentity_t	*nextTrain;
    	gentity_t	*prevTrain;
    	vec3_t		pos1, pos2;
    
    	char		*message;
    
    	int			timestamp;		// body queue sinking, etc
    
    	float		angle;			// set in editor, -1 = up, -2 = down
    	char		*target;
    	char		*targetname;
    	char		*team;
    	char		*targetShaderName;
    	char		*targetShaderNewName;
    	gentity_t	*target_ent;
    
    	float		speed;
    	vec3_t		movedir;
    
    	int			nextthink;
    	void		(*think)(gentity_t *self);
    	void		(*reached)(gentity_t *self);	// movers call this when hitting endpoint
    	void		(*blocked)(gentity_t *self, gentity_t *other);
    	void		(*touch)(gentity_t *self, gentity_t *other, trace_t *trace);
    	void		(*use)(gentity_t *self, gentity_t *other, gentity_t *activator);
    	void		(*pain)(gentity_t *self, gentity_t *attacker, int damage);
    	void		(*die)(gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod);
    
    	int			pain_debounce_time;
    	int			fly_sound_debounce_time;	// wind tunnel
    	int			last_move_time;
    
    	int			health;
    
    	qboolean	takedamage;
    
    	int			damage;
    	int			splashDamage;	// quad will increase this without increasing radius
    	int			splashRadius;
    	int			methodOfDeath;
    	int			splashMethodOfDeath;
    
    	int			count;
    
    	gentity_t	*chain;
    	gentity_t	*enemy;
    	gentity_t	*activator;
    	gentity_t	*teamchain;		// next entity in team
    	gentity_t	*teammaster;	// master of the team
    
    	int			kamikazeTime;
    	int			kamikazeShockTime;
    
    	int			watertype;
    	int			waterlevel;
    
    	int			noise_index;
    
    	// timing variables
    	float		wait;
    	float		random;
    
    	gitem_t		*item;			// for bonus items
    };
    This whole entity is passed to the engine at runtime, but only the first two fields are declared for the engine:

    Code:
    // the server looks at a sharedEntity, which is the start of the game's gentity_t structure
    typedef struct {
    	entityState_t	s;				// communicated by server to clients
    	entityShared_t	r;				// shared by both the server system and game
    } sharedEntity_t;
    My problem is that I need to access the health field of gentity_t from the engine. Technically, this is possible, but the health field is not declared in sharedEntity (which is the same memory address than gentity_t in the gamecode), so this is not straightforward.

    I am looking for an elegant way to do this, and my constraint is that I must not edit the gamecode, only the engine.

    The solutions I've thought:

    - Just copy the whole gentity_t fields into sharedEntity_t. This would work I think but would be redundant, and I would like to avoid copying this huge set of fields.

    - Include the two headers files declaring the gentity_t and sharedEntity_t structs, and create a Getter and a Setter functions that would cast a gentity_t over a sharedEntity_t and return/set a field. The problem is that I can't simply include them because they are both including some common headers files and this produce a recursive include error (and I can't modify the files to add a check, these are normally in the gamecode).

    - Directly access the health field using a clever memory pointer, but I don't even know if that's possible given the huge number of fields prior health with many different types?

    ------

    I humbly ask for any help or idea on how to do this.

    Thank you for reading me,
    Stephen L.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Accessing a limited struct's fields

    Quote Originally Posted by lrq3000 View Post
    Directly access the health field using a clever memory pointer, but I don't even know if that's possible given the huge number of fields prior health with many different types?
    To get a pointer to a particular field, try the offsetof() macro.

    http://www.cplusplus.com/reference/c...ddef/offsetof/

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Accessing a limited struct's fields

    I'd just cast the pointer if you are sure it is the correct type.

    Quote Originally Posted by Paul McKenzie View Post
    To get a pointer to a particular field, try the offsetof() macro.

    http://www.cplusplus.com/reference/c...ddef/offsetof/

    Regards,

    Paul McKenzie
    Would offsetof be "smarter/better" than pointer casting? Honest question.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)