2012-03-08 18 views
6

Estoy escribiendo una extensión de Ruby C donde estoy usando math.h. Se está compilando tanto en OSX como en Windows. En Windows uso nmake que viene con Visual Studio Express C++ 2010.¿Cómo se define una función en C si no se ha definido antes?

Encontré que VS no incluía la función round() en su math.h. Por lo que añade esto a compensar:

static inline double round(double value) 
{  
    return floor(value + 0.5); 
} 

que por supuesto ha causado un error al compilar en OSX como round() se define. (El error real Creo que se me había declarado que la mina estática después de que ya se ha declarado una versión no estática.

pesar de todo, me gustaría evitar la redefinición de la función si existe.

En el momento en que tengo esta condición:.?

#ifdef _WIN32 
static inline double round(double value) 
{  
    return floor(value + 0.5); 
} 
#endif 

que trabajaba en mi escenario - pero parece un poco genérico que quiero decir, ¿y si puedo compilar con un compilador diferente en Windows

Así que mi pregunta es, ¿Puedo detectar si una función ya está definida y entonces evite definirlo yo mismo?

O, ¿puedo detectar específicamente el uso del compilador nmake - cl Creo que es?

Creo que idealmente podría detectar si la función ya está definida, ya que parece ser el método más robusto.

Respuesta

0

me encontré con que la utilidad MKMF de Ruby tiene un método have_func que se puede utilizar para comprobar la existencia de funciones: http://apidock.com/ruby/Object/have_func

he añadido a mi archivo have_func('round', 'math.h')extconf.rb que luego me dio una constante HAVE_ROUND preprocesador.

Entonces podría definir de manera segura y vuelta() a mí mismo que no existía:

#ifndef HAVE_ROUND 
static inline double round(double value) 
{  
    return floor(value + 0.5); 
} 
#endif 

funcionó a la perfección! :)

2

Eso funcionó en mi situación, pero parece un poco genérico. Quiero decir, ¿y si compilo con un compilador diferente en Windows?

  1. Genérico es bueno.
  2. No importa qué compilador use; simplemente está verificando si se define un símbolo. Podrías definir ese símbolo usando cualquier compilador, no importa. ifdef s son generalmente la forma en que maneja los problemas de portabilidad.
  3. round está definido por el estándar C99. VS no es compatible con C99 en este momento, es por eso que falta.
+0

Mi preocupación era que, si por ejemplo actualizaba Visual Studio y 'math.h', entonces incluía' round() '- entonces habría un conflicto como en OSX. Por eso pensé que buscar la característica en lugar del entorno era una mejor idea. Es la línea de pensamiento que tengo desde el desarrollo web donde se prueban las características en lugar de olfatear la cadena de agente de usuario. – thomthom

+0

@thomthom: Sí, pero esto no es un desarrollo web =). Así es como lo haces en general. A veces, cuando cambias los compiladores, las cosas se rompen y tienes que arreglarlas, pero se puede evitar en su mayor parte. En este caso, 'round' se agregó en C99. VS no es compatible con C99, por lo que no está presente. –

+0

El autoconf de GNU utiliza el enfoque basado en características, # constantes de definición de la forma 'HAVE_feature'. Por ejemplo, puede definir 'HAVE_ROUND'. Como es dependiente del compilador en este caso, podría hacer un "-DHAVE_ROUND = 0" en las definiciones del preprocesador C en su comando de compilación; déjalo indefinido bajo compiladores que tienen round(). El contenedor alrededor de su función round() leería '# si está definido (HAVE_ROUND) &&! HAVE_ROUND ... function declaration ... # endif'. –

0

Lo que ha hecho es la forma correcta de tratar las incompatibilidades.

Ha notado que esta forma de lidiar con las incompatibilidades dependientes del sistema no es "genérica", pero, al contrario de los lenguajes como JAVA que abstrae tales problemas, tiene que ocuparse de tales cosas. Por otro lado, siempre obtendrá el mejor rendimiento que ofrece la plataforma.

Cuestiones relacionadas