Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Portable way of testing if a function exist

Reply
Thread Tools

Portable way of testing if a function exist

 
 
mathieu
Guest
Posts: n/a
 
      12-06-2008
Hi there,

I am using the following piece of code (*) to determine whether or
not a particular function exist. It is working fine most of the time,
but I recently got a case where it shows limitation: builtins
functions. For instance compiling it with a recent gcc version leads
to:

$ gcc -DCHECK_FUNCTION_EXISTS=strncasecmp -o CheckFunctionExists.o -
c CheckFunctionExists.c
CheckFunctionExists.c:3: warning: conflicting types for built-in
function ‘strncasecmp’

Any suggestion on a better way to do that ?

Thanks!
-Mathieu

(*)
#ifdef CHECK_FUNCTION_EXISTS

char CHECK_FUNCTION_EXISTS();
#ifdef __CLASSIC_C__
int main(){
int ac;
char*av[];
#else
int main(int ac, char*av[]){
#endif
CHECK_FUNCTION_EXISTS();
if(ac > 1000)
{
return *av[0];
}
return 0;
}

#else /* CHECK_FUNCTION_EXISTS */

# error "CHECK_FUNCTION_EXISTS has to specify the function"

#endif /* CHECK_FUNCTION_EXISTS */
 
Reply With Quote
 
 
 
 
nicolas.sitbon@gmail.com
Guest
Posts: n/a
 
      12-06-2008
On 6 déc, 10:47, mathieu <(E-Mail Removed)> wrote:
> Hi there,
>
> * I am using the following piece of code (*) to determine whether or
> not a particular function exist. It is working fine most of the time,
> but I recently got a case where it shows limitation: builtins
> functions. For instance compiling it with a recent gcc version leads
> to:
>
> $ gcc *-DCHECK_FUNCTION_EXISTS=strncasecmp -o CheckFunctionExists.o * -
> c CheckFunctionExists.c
> CheckFunctionExists.c:3: warning: conflicting types for built-in
> function ‘strncasecmp’
>
> Any suggestion on a better way to do that ?
>
> Thanks!
> -Mathieu
>
> (*)
> #ifdef CHECK_FUNCTION_EXISTS
>
> char CHECK_FUNCTION_EXISTS();
> #ifdef __CLASSIC_C__
> int main(){
> * int ac;
> * char*av[];
> #else
> int main(int ac, char*av[]){
> #endif
> * CHECK_FUNCTION_EXISTS();
> * if(ac > 1000)
> * * {
> * * return *av[0];
> * * }
> * return 0;
>
> }
>
> #else */* CHECK_FUNCTION_EXISTS */
>
> # *error "CHECK_FUNCTION_EXISTS has to specify the function"
>
> #endif /* CHECK_FUNCTION_EXISTS */


try with -fno-builtin.
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      12-06-2008
mathieu wrote:
> Hi there,
>
> I am using the following piece of code (*) to determine whether or
> not a particular function exist. It is working fine most of the time,
> but I recently got a case where it shows limitation: builtins
> functions. For instance compiling it with a recent gcc version leads
> to:
>
> $ gcc -DCHECK_FUNCTION_EXISTS=strncasecmp -o CheckFunctionExists.o -
> c CheckFunctionExists.c
> CheckFunctionExists.c:3: warning: conflicting types for built-in
> function ‘strncasecmp’
>
> Any suggestion on a better way to do that ?


Yes: Read the documentation that comes with your C
implementation. "That's not automated," you may object,
but neither is the process of compiling, linking, and
looking for error messages. (If any; see below.)

> #ifdef CHECK_FUNCTION_EXISTS
>
> char CHECK_FUNCTION_EXISTS();


If the function *does* exist, and if this declaration
doesn't match the function's actual type, the behavior is
undefined. You may or may not get an error message; the
message may even amount to "no such function" even if a
function by that name does in fact exist. If you get no
error message you can conclude that the function exists,
but the presence of a message is not foolproof evidence
that the function is absent.

> #ifdef __CLASSIC_C__


Bad choice of macro name: All identifiers beginning
with two underscores are reserved.

> int main(){
> int ac;
> char*av[];


Missing a { here.

> #else
> int main(int ac, char*av[]){
> #endif
> CHECK_FUNCTION_EXISTS();
> if(ac > 1000)
> {
> return *av[0];
> }
> return 0;
> }
>
> #else /* CHECK_FUNCTION_EXISTS */
>
> # error "CHECK_FUNCTION_EXISTS has to specify the function"


The #error directive wasn't standardized until the ANSI
document was adopted in 1989, so if you still want to cater
to "classic C" you should probably avoid using it.

> #endif /* CHECK_FUNCTION_EXISTS */


Again: RTFM. It's a much better way, and will tell you
useful things like what the rewindWidget() function does,
what arguments it takes, and what special compiler flags
you need to use to get at it.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
mathieu
Guest
Posts: n/a
 
      12-07-2008
On Dec 6, 3:06*pm, Eric Sosman <(E-Mail Removed)> wrote:
> mathieu wrote:
> > Hi there,

>
> > * I am using the following piece of code (*) to determine whether or
> > not a particular function exist. It is working fine most of the time,
> > but I recently got a case where it shows limitation: builtins
> > functions. For instance compiling it with a recent gcc version leads
> > to:

>
> > $ gcc *-DCHECK_FUNCTION_EXISTS=strncasecmp -o CheckFunctionExists.o * -
> > c CheckFunctionExists.c
> > CheckFunctionExists.c:3: warning: conflicting types for built-in
> > function ‘strncasecmp’

>
> > Any suggestion on a better way to do that ?

>
> * * *Yes: Read the documentation that comes with your C
> implementation. *"That's not automated," you may object,
> but neither is the process of compiling, linking, and
> looking for error messages. *(If any; see below.)
>
> > #ifdef CHECK_FUNCTION_EXISTS

>
> > char CHECK_FUNCTION_EXISTS();

>
> * * *If the function *does* exist, and if this declaration
> doesn't match the function's actual type, the behavior is
> undefined. *You may or may not get an error message; the
> message may even amount to "no such function" even if a
> function by that name does in fact exist. *If you get no
> error message you can conclude that the function exists,
> but the presence of a message is not foolproof evidence
> that the function is absent.
>
> > #ifdef __CLASSIC_C__

>
> * * *Bad choice of macro name: All identifiers beginning
> with two underscores are reserved.
>
> > int main(){
> > * int ac;
> > * char*av[];

>
> * * *Missing a { here.
>
> > #else
> > int main(int ac, char*av[]){
> > #endif
> > * CHECK_FUNCTION_EXISTS();
> > * if(ac > 1000)
> > * * {
> > * * return *av[0];
> > * * }
> > * return 0;
> > }

>
> > #else */* CHECK_FUNCTION_EXISTS */

>
> > # *error "CHECK_FUNCTION_EXISTS has to specify the function"

>
> * * *The #error directive wasn't standardized until the ANSI
> document was adopted in 1989, so if you still want to cater
> to "classic C" you should probably avoid using it.
>
> > #endif /* CHECK_FUNCTION_EXISTS */

>
> * * *Again: RTFM. *It's a much better way, and will tell you
> useful things like what the rewindWidget() function does,
> what arguments it takes, and what special compiler flags
> you need to use to get at it.


I said "portable", I am targeting unknown system with unknown
compiler. Please Read the Fine Subject Line.

This is used internally in cmake and works everywhere, except in the
very particular case of -Werror and recent gcc version with builtins
functions.

-M

 
Reply With Quote
 
David Thompson
Guest
Posts: n/a
 
      12-15-2008
On Sat, 6 Dec 2008 01:47:56 -0800 (PST), mathieu
<(E-Mail Removed)> wrote:

> char CHECK_FUNCTION_EXISTS();
> #ifdef __CLASSIC_C__


As already said, that's a poor choice of macroname. Why not just do
#ifndef __STDC__ ? That's guaranteed to work for conforming
implementations, and while the standard can't actually apply to
nonconforming ones, if there had been any that had a problem with it
there would already have been a big stink 19 years ago.

> int main(){
> int ac;
> char*av[];


This was never valid, even _before_ K&R1. You need
int main (ac,av) int ac; char *av[]; /* or **av */ {

> #else
> int main(int ac, char*av[]){
> #endif
> CHECK_FUNCTION_EXISTS();


Calling a function that actually takes parameters (which your example
of strncasecmp does) without giving it the arguments is Undefined
Behavior and is likely to screw up badly on quite a few systems.
Declaring a function with the wrong return type, as you did and was
diagnosed, and calling it and ignoring the putative result, is also
Undefined Behavior but in practice is much less likely to screw up.

Unless you're only compiling and not running this code. But that's not
a sufficient check; I know at least one system that will successfully
compile (and link) a reference to an unavailable function, and fail
only when run. (Which is permitted by the C standards.)

> if(ac > 1000)
> {
> return *av[0];
> }


This is just silly. No one should want to run this program with 1001
arguments, not even in an automated environment. If you actually want
to have some nontrivial (i.e. testable) functionality, I would suggest
something more like
if( ac >= 2 ) return atoi (av[1]);
/* yes atoi() isn't the safest, but here that's lost in the weeds */
or even
if( ac >= 2 && isdigit((uchar)av[1][0]) ) return av[1][0] - '0';

OTOH if you're actually hoping for reliable evidence of the screwup(s)
mentioned above, you're in fantasyland.

> return 0;
> }


You're probably better off #include'ing all the standard headers that
appear to exist (as files) on your system, including standards other
than C e.g. POSIX if you want, turning on all the extension macros you
know about (which generally do no harm if you specify them when they
aren't applicable), and trying to compile a _type-valid_ call to the
desired function. This still isn't 100%, but it's closer.

But please have some way for a (competent) human to override or alter
the results. Hopefully it won't be needed often, but if it's needed
and not possible you will make some users very unhappy.

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      12-15-2008
David Thompson <(E-Mail Removed)> writes:
> On Sat, 6 Dec 2008 01:47:56 -0800 (PST), mathieu
> <(E-Mail Removed)> wrote:
>> char CHECK_FUNCTION_EXISTS();
>> #ifdef __CLASSIC_C__

>
> As already said, that's a poor choice of macroname. Why not just do
> #ifndef __STDC__ ? That's guaranteed to work for conforming
> implementations, and while the standard can't actually apply to
> nonconforming ones, if there had been any that had a problem with it
> there would already have been a big stink 19 years ago.

[...]

I seem to recall that some pre-conforming implementations defined
__STDC__ as 0.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
David Thompson
Guest
Posts: n/a
 
      12-29-2008
On Mon, 15 Dec 2008 08:18:03 -0800, Keith Thompson <(E-Mail Removed)>
wrote:

> David Thompson <(E-Mail Removed)> writes:
> > On Sat, 6 Dec 2008 01:47:56 -0800 (PST), mathieu
> > <(E-Mail Removed)> wrote:
> >> char CHECK_FUNCTION_EXISTS();
> >> #ifdef __CLASSIC_C__

> >
> > As already said, that's a poor choice of macroname. Why not just do
> > #ifndef __STDC__ ? That's guaranteed to work for conforming
> > implementations, and while the standard can't actually apply to
> > nonconforming ones, if there had been any that had a problem with it
> > there would already have been a big stink 19 years ago.

> [...]
>
> I seem to recall that some pre-conforming implementations defined
> __STDC__ as 0.


Good point. I don't recall if pre/nonstd preprocessors did unknown
pp-id is zero, which would allow #if; probably not. Oh well.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: testing -- what to do for testing code with behaviour dependantupon which files exist? Brian van den Broek Python 2 04-04-2005 11:37 PM
testing -- what to do for testing code with behaviour dependant uponwhich files exist? Brian van den Broek Python 3 04-03-2005 12:28 AM
Does my object exist? So why its HWND doesn't exist? That's a question... (CMonthCalCtrl control) LT C++ 7 07-25-2004 07:08 PM
In Schema, how to say "If one element exist, another element must exist"? Y.S. XML 3 09-17-2003 02:51 PM
Help:Why can't I use namespace System.Web? It is said that this namespace doesn't exist. But it should exist. Èý¹â ASP .Net 1 07-29-2003 04:31 PM



Advertisments