Solved

Modeling structures to objects

Posted on 1998-06-15
8
247 Views
Last Modified: 2010-04-15
Ok, what I want is to model the well known struct to objects, including into these pointers to the operations,
somehting like this:

typedef struct o_Some{

   /*Attributes*/
   t_Some r;
   o_List    o;      /*Other object like this*/
   char      fn[90];
   
   /* Operations*/
   int (*Init)(o_Some *Self);
   int (*Done)(o_Some *Self);
   int (*Load)(o_Some *Self, int Idx);
   int (*Save)(o_Some *Self);
   }o_Some;

But what I want is some method to avoid passing all operations the address of the Object. Is there any
way to resolv the address from the caller structure?, Or any other way to program objects in C standard?,
I am currently using gcc into a Linux Box!

Thank you in advance,
0
Comment
Question by:trickle
  • 4
  • 3
8 Comments
 
LVL 11

Accepted Solution

by:
alexo earned 200 total points
Comment Utility
It is not possible to avoid passing the pointer to the "object".

Consider C++ for example.  Every method has a hidden pointer argument that points to the current object (the "this" pointer, similar to your "Self").  Remember that C++ was initially translated into C.

You can hide the passing of the pointer by a clever use of preprocessor macros but you cannot avoid it.
0
 
LVL 11

Expert Comment

by:alexo
Comment Utility
The function must get the pointer to the correct structure somehow and the only fail-safe method is to pass it in an argument (on the stack).
0
 
LVL 11

Expert Comment

by:alexo
Comment Utility
On the other hand, why not use C++?
It already has the mechanism that deals with objects built-in, along with stricter type checking and other goodies.  And, as far as I remember, GCC compiles C++ code.
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
It is not clear exactly WHAT 'object' behaviour you are trying to achieve in C .. are you just trying to achieve polymorphism (virtual functions?) .. inheritance? .. classes?

Do you want all your objects to be only struct o_Some instances (same data members), but allow for individual o_Some instances to respond to the methods Init etc differently?  Or do you want to have other structs which are 'derived' from a common struct (eg. o_Some and o_Other each derive from o_Base)?

In either case, don't store ALL the function pointers directly in the object.  Instead, store a POINTER to a strut containing the function pointers.  This way, the table can be shared by multiple objects.

The first case is probably easier, as there is no inheritance involved .. just the one struct.  Try something like this...

struct Methods;

typedef const struct Methods* MethodsPointer;

struct o_Some {
   /*Methods*/
   MethodsPointer call;
   /*Attributes*/
   t_Some r;
   o_List    o;      /*Other object like this*/
   char      fn[90];
} o_Some;

typedef struct Methods {
   int (*Init)(o_Some *Self);
   int (*Done)(o_Some *Self);
   int (*Load)(o_Some *Self, int Idx);
   int (*Save)(o_Some *Self);
} Methods;

Now you can create a Methods object and set it up to point to the appropriate functions.  Then when you create an o_Some object, set the 'call' member to point to a Methods object.

To implement different behaviour for some objects, simply change their 'call' member to point to a DIFFERENT Methods object which is set up with some (or all) of the function pointers pointing to other functions.

eg. in you startup code, you would do
  Methods Standard;
  Methods Special;
  ...
  Standard.Init = Special.Init = xxx;
  Standard.Load = yyy;
  Special.Load = zzz;

Here the Init method (xxx) is shared, but the load method can be different.

Now when you create o_Some instances.
  o_Some x, y;
  x.call = &Standard;
  y.call = &Special;
  x.call->Init(x);
  y.call->Init(y);
  x.call->Load(x,1);
  y.call->Load(y,1);

You can use macros to help get this right.  eg.
  #define CONSTRUCT(_x,_t) _x.call = &_t
  #define CALL(_x,_f) _x.call->_f(_x)
  #define CALL1(_x,_f,_p1) _x.call->_f(_x,p1)
  #define INIT(_x) CALL(_x,Init)
  #define LOAD(_x,p1) CALL1(_x,Load,_p1)
and then say...
  o_Some x,y;
  CONSTRUCT(x,Standard);
  CONSTRUCT(y,Special);
  INIT(x); LOAD(x,1);
  INIT(y); LOAD(y,1);

Another idea is to use a function instead of/ as well as #define macros .. eg.
   int Init (o_Some* Self) {
     return CALL(Self,Init);
   }
you may even get clever, and write a macro to generate these function calls!!  Now you can just say 'Init(x)' .. and better still, 'Init' is a true function .. so you can put it (and expose it) in a library (or dll etc).

Now onto the more complex case of inheritance...

If you want to allow for inheritance, where one 'struct' inherits from another 'struct' and can add its own member variables, then you need to get a little trickier.

eg.
struct Methods;

typedef const struct Methods* MethodsPointer;

struct o_Base {
   /*Methods*/
   union {
     MethodsPointer call;
   } access;
   /*Attributes*/
   t_Some r;
   o_List    o;      /*Other object like this*/
} o_Base;

struct o_Some {
   /*Methods*/
   union {
     MethodsPointer call;
     o_Base base;
   } access;
   /*Attributes*/
   char      fn[90];  /* NOTE: other members are inherited */
} o_Some;

struct o_Other {
   /*Methods*/
   union {
     MethodsPointer call;
     o_Base base;
   } access;
   /*Attributes*/
   int  n;        /* NOTE: other members are inherited */
} o_Other;

typedef struct Methods {
   int (*Init)(void*Self);
   int (*Done)(void*Self);
   int (*Load)(void*Self, int Idx);
   int (*Save)(void*Self);
} Methods;

Note that we need void* because Init can take a o_Base, o_Some or o_Other.  The function itself needs to do a cast (yuck).

now you can set up the function tables for each class...
  Methods Base, Some, Other;
change the macros slightly to use ".access"...
  #define CONSTRUCT(_x,_t) _x.access.call = &_t
  #define CALL(_x,_f) _x.access.call->_f(_x)
  #define CALL1(_x,_f,_p1) _x.access.call->_f(_x,p1)
and you can call like this...
  o_Base b;
  o_Some x;
  o_Other y;
  CONSTRUCT(b,Base);
  CONSTRUCT(x,Some);
  CONSTRUCT(y,Other);
  INIT(b); LOAD(b,1);
  INIT(x); LOAD(x,1);
  INIT(y); LOAD(y,1);
where the approriate function is called depending on the 'class' of the object

The tricks now are that you need to use ".access.base" to get at inherited base class members. eg.
  x.access.base.r
AND you have to cast correctly in your member functions.

You should be able to safely cast from a o_Some to a o_Base as having the union as a first member should ensure that all is ok.

I Hope this helps you.

NOTE:
You may wish to reopen the question before grading and tell us which expert's answers/comments you prefer.  Then the relevant expert can propose an answer for you.

0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 11

Expert Comment

by:alexo
Comment Utility
>> You may wish to reopen the question before grading and tell us which expert's answers/comments you prefer.

Letting the question go stale and the autograder intervene is much easier...
0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Seems to be a trend .. get the info you want then don't bother grading.
0
 

Author Comment

by:trickle
Comment Utility
Sorry but I'm too busy!. The question was proposed because we are upgrading our DCE with SQL support (I mean ODBC bridge), and all our objects are in C standard and we needed inheritance and polimorphism in a simply way.

The answer I prefer is from RONSLOW, because all possibilities are studied (I mean that just use C++ is not a valid answer for me) and all the capabilities from C++ take place in the exposition from RONSLOW. I'm worry for the delay but I'm too busy (again).
If you have any comments to help us to implement a subsystem message driven (in the network framework), who handles SQL entries and :
   + Generates a new SQL object with the Parser, ..., methods and the Interface to access the Objects DataBase, into a binary packet who is handled from our packet layer where is the scheduler and the timer and the theathing.
   + Send back the answer.

Oh! I'm bothering you...

All the very best.
   

0
 
LVL 10

Expert Comment

by:RONSLOW
Comment Utility
Unfortunately you didn't accept/reject an answer in time, and so I missed out on being able to propose my comments as an answer, let alone be rewarded with a grade.

If you did find my answer most helpful, then might I suggest you post another question with a title like "For RONSLOW" that I can answer to get my just desserts.

Regarding your question about implementing this subsystem, it is too large a question and too specific to be added on here .. if you really would like comments on this, please post a new question .. but it would be best to post separate questions for specific problems .. that way you are more likely to get a response.  Hopefully the experts won't be too busy to answer you :-)


0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now