简体   繁体   中英

How do I resolve this warning about passing a function pointer to a macro in C?

I have a macro defined as:

#define _call(func_name, __func_proto, ...)        {       \
 void *_handle;                                           \
 int result = !CERR_V_SUCCESS;                               \
                                                              \
  _handle = dlopen(_DLL_NAME,GLOBAL); \
  if (_handle) {                                           \
      __func_proto = dlsym(dll_handle, func_name);            \
      if (__func_proto) {                                     \
          result = (*__func_proto)(__VA_ARGS__);              \
     }                                                       \
      (void)dlclose(_handle);                              \
  }                                                           \
  return (result);                                            \
}

I am calling this macro with different function pointers like this:

_call("download",_download,src,dst);
_call("upload",_upload,src,dst);
_call("test",_test,file);

and the function pointers are defined as

int (*_download )(int *,int *);
int (*_upload)(int *,int*);
int (*_test)(int *,char*);

This results in a warning a value of type "void *" cannot be assigned to an entity of type "int (*)(int*,int*)" .

How can I resolve this warning?

Documentation of dlsym suggests you should cast the function pointer to void* before you assign its return value to the pointer:

*(void **)(&__func_proto) = dlsym(dll_handle, func_name);

Rationale is described behind the link:

The ISO C standard does not require that pointers to functions can be cast back and forth to pointers to data. Indeed, the ISO C standard does not require that an object of type void * can hold a pointer to a function. Implementations supporting the XSI extension, however, do require that an object of type void * can hold a pointer to a function.

Note that compilers conforming to the ISO C standard are required to generate a warning if a conversion from a void * pointer to a function pointer is attempted as in:

fptr = (int (*)(int))dlsym(handle, "my_function");

You need to add casts, since void * doesn't convert to/from function pointers automatically. In fact it's non-portable to assume that function pointers can be expressed as void * at all.

Of course, if you're on a system that has dlopen() and friends, it can be a sure assumption that that platform supports this conversion.

Also, it sounds very strange to do the whole dlopen() / dlsym() / dlclose() dance per call , usually you buffer the pointers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM