Hi, I am studying a code but I am having difficulties...
Here it is:
struct drm_driver_descriptor
{
const char *name;
const char *driver_name;
struct pipe_screen* (*create_screen)(int drm_fd);
const struct drm_conf_ret *(*configuration) (enum drm_conf conf);
};
extern struct drm_driver_descriptor driver_descriptor;
typedef void (*func_pointer)(void);
static INLINE func_pointer
pointer_to_func( void *p )
{
union {
void *p;
func_pointer f;
} pf;
pf.p = p; /*pf.f has no attribution*/
What do you mean by no attribution? pf.f has type pointer to function
taking one argument (of type pointer to void) and not returning any
value (sometimes expressed as returning void). As a result of this
assignment, it also has a value. What that value is and whether it is
valid or not is system dependent. Given that pf.f and pf.p may have
different sizes, all we can say is that corresponding bits which are
common to both have the same value.
If pf.p is shorter than pf.f, the extra bits in pf.f are
indeterminate. If the opposite, then the extra bits in pf.p are
ignored in the return statement that follows. Even if they are the
same size, there is no guarantee that the bit pattern of the parameter
p (which is what is stored in pf.p) are a legal pattern when evaluated
as the value of a pointer to function (which is the type of pf.f used
in the return statement). It could be trap representation.
return pf.f;
}
dd = (const struct drm_driver_descriptor *) pointer_to_func(dlsym(library, "driver_descriptor"); /*here how could pointer_to_func which returns func_pointer which is not attributed to anything be casted to struct drm_driver_descriptor?*/
Since this statement has unbalanced parentheses, you probably typed it
in manually. You should really use cut and paste to preserve the
accuracy of the code in question.
What do you mean by attributed? From the code in this statement, it
appears that dlsym returns a pointer value. That value is either a
pointer to void (in which case it is passed directly to
pointer_to_func) or a pointer to some object type (in which case it is
implicitly converted to pointer to void and the converted value passed
to pointer_to_func). In both cases, pointer_to_func receives a void*
value and returns a pointer to function value. The cast operator then
converts that pointer to function value to pointer to structure value.
AT NO TIME IS THE POINTER VALUE CONVERTED TO A STRUCT VALUE. The
pointer value is converted from one type of pointer to another type of
pointer. This particular conversion between a function to pointer and
a function to object is something the standard does not describe.
Consequently, unless your system documents what this conversion is,
the code is relying on unspecified (or possibly undefined) behavior.
The sample you provided makes no sense since the conversion could be
performed much more simply with
dd = (const struct drm_driver_descriptor *)
dlsym(library, "driver_descriptor");
There is no need for an intermediate conversion to a function pointer
when converting between to types of object pointers.
And latter there is code like: dd->create_screen(...);
How could it be so?
How could what be so? dd is a pointer to structure. create_screen is
a member of that structure. Somewhere in the code you did not show
that member is assigned a value (the address of a function). This
code simply calls that function. The -> operator is the correct tool
to access the member of a structure when you have the address of that
structure.