This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Is there a better way to solve this requirement

I have a different objects, like this:

typedef struct
{
    int32_t  info ;
} item1_properties_t ;

and

typedef struct
{
    int32_t  info ;
} item2_properties_t ;

the objects are held in containers. I want to introduce a function that returns these objects (i.e. a const pointer) with minimum casts (working in C). I thought of having the function return the type and a void pointer, expecting the caller to cast correctly but I don't really like it. Do you have better ideas?

  • "I thought of having the function return the type"

    A 'C' function cannot return a type.

  • Why do you need a "generic" function that may sometimes return property values for an "item1" object and sometimes properties for a "item2" object?

    If the property structures are always looking the same (as they just happen to do in your example) then you wouldn't have any problems.

    And if the property structures do look different for different objects, then the user of the structure must know what type of object so it knows what type of property type so it knows what to do. But then, that function should be able to call different "get_property" functions. And then you wouldn't have any problem with data types.

    So please start by explaining what "trick" you are busy trying to implement, and what you hope to solve with this "trick".

  • Seems like you want things like run-time type identification and dynamic type casting. Those are present in C++, but you won't find them in C.
    Only static (i.e. compile-time) type checking can be performed in C. Whatever you are trying to do, this is not the way to do it in C.

  • I have a container that refers to other objects by maintaining their type and identifier(just a numbers). Then I have separate static containers to hold the structs themselfes. I want to write a function that given an object id, will return a pointer to that object. I am aware of the limitations of C in that regard, I was hoping somebody can offer a better approach. The unified structure method will work of course but I don't think all structures will have a common layout. Creating separate "get property" functions will not work well as the structures are fill by a .xml file whose contents are not know in advance. Yes it is possible but not 100% catholic...So I was thinking of making that "get pointer to object" function return the type of the addressed object via an output argument and a pointer, that will be cast according to the returned type.

  • It doesn't matter that you fill your structures from XML.

    What is relevant is that you have a container containing objects of mixed type.

    To be able to process the different properties (that have different types depending on the type of object) you do need some part of the code to care about the object type.

    So even if you have a generic void pointer for each object, you need a function:
    get_type_of_object(generic_ptr)

    And while a generic get_property(generic_ptr) function could contain a switch statement to figure out what type of object so it knows what properties to return, it would have to return a generic answer.

    So the caller of get_property(generic_ptr) would have to also contain a switch statement to figure out what to do with the returned value from that generic get_property() function.

    So then the caller could already from the start have had a switch statement that decided the type of object, and called a specialized get_xx_property() or get_yy_property() in which case it will directly receive a correct property struct.

    The switch() statements can be replaced by manually created virtual functions - i.e. every object contains a couple of function pointers:
    print_me()
    process_properties()
    load()
    save()

    But as soon as you want a generic loop to retrieve properties from an object of unknown type and then do something with these properties, then that loop needs code to decode type, making the code non-generic.

    You must figure out where in your design you want to introduce that decoding of data type, or if you can move all processing into type-specific functions, so that you can have all objects changed into a reference to a type-specific function pointer table and a list of type-specific information that the type-specific functions knows how to handle. Then the type-specific functions can directly perform a type cast to their specific type since only the correct object type will point to that specific function pointer table.

    If you happen to intend to use a 8051 chip, then function pointers are bad because of the special code generation used by the C51 compiler, so you have to settle for switch statements and just figure out where to place them.

  • Thanks for the reply. I'm using an ARM type processor so it's OK. Thanks all the time.

  • Seems he want to implement the PC software design to embedded system, not good :)

  • I don't see a direct connection with PC software here - it's just a requirement that can be more easily satisfied using another programming model (in this case, object oriented programming).

  • object oriented (OO) design pattern is generally used in pc software development.

  • Is widely used in many fields of application!

  • What the OP can do is store the data of the containers as an array of bytes alongside the type of the data. Then, when pointer/copying that data to a coitainer, a cast can be done based on the stored type.

  • What the OP can do is store the data of the containers as an array of bytes alongside the type of the data. Then, when pointer/copying that data to a coitainer, a cast can be done based on the stored type.

  • You mean something like this

    enum { char_type, int_type, long_type } ;
    
    switch( type-id )
    {
       case char_type:
          char_result = (char)input;
          break;
    
       case int_type:
          int_result  = (int)input;
          break;
    
       case long_type:
          long_result = (long)input;
          break;
    
    }
    

  • I already said something similar, but the importany thing here is that such a byte-array must contain an exact image of the structure stored in it. If so, getting data out of the generic container is as simple as copying it/pointing to it, and performing one cast.