2012-03-08 16 views
6

Piszę rozszerzenie Ruby C, w którym używam math.h. Jest kompilowany na systemach OSX i Windows. W systemie Windows korzystam z wersji nmake dostarczanej wraz z Visual Studio Express C++ 2010.Jak zdefiniować funkcję w C, jeśli nie została wcześniej zdefiniowana?

Zauważyłem, że funkcja VS nie zawiera funkcji round() w ich math.h. Więc dodałem to do wyrównania:

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

To z kursu spowodował błąd przy kompilacji pod OSX jak round() nie jest zdefiniowana. (Rzeczywista błąd myślę, że bym został ogłoszony po kopalni statyczny to już uznany za wersję non-statyczne.

Niezależnie od tego, chciałbym uniknąć redefinicji funkcji, jeśli nie istnieje.

Na moment mam ten warunkowy.?

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

to działało w moim scenariuszu - ale wydaje się nieco rodzajowy mam na myśli, co zrobić, jeśli mogę skompilować z innego kompilatora pod Windows

Więc moje pytanie brzmi: mogę wykryć, czy funkcja jest już zdefiniowana, i to unikaj samodzielnego definiowania?

Czy mogę wykryć konkretnie kompilator nmake użyć - cl Myślę, że tak?

Myślę, że najlepiej byłoby móc wykryć, czy funkcja jest już zdefiniowana, ponieważ wydaje się być najbardziej niezawodną metodą.

Odpowiedz

0

stwierdziliśmy, że mkmf narzędzie Ruby ma metodę have_func, które można użyć do sprawdzenia istnienia funkcji: http://apidock.com/ruby/Object/have_func

dodałem have_func('round', 'math.h') do mojego extconf.rb pliku, który następnie dał mi stałą HAVE_ROUND preprocesora.

Wtedy mógłbym bezpiecznie określić round() sobie, że to nie istnieje:

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

Pracował doskonale! :)

2

To działało w moim scenariuszu - ale wydaje się nieco ogólne. Mam na myśli, co jeśli kompiluję z innym kompilatorem pod Windows?

  1. Ogólne jest dobre.
  2. Nie ma znaczenia, jakiego kompilatora używasz; po prostu sprawdzasz, czy zdefiniowany jest symbol. Możesz zdefiniować ten symbol za pomocą dowolnego kompilatora, to nie ma znaczenia. ifdef s to zazwyczaj sposób obsługi problemów z przenośnością.
  3. round jest zdefiniowany przez standard C99. VS obecnie nie obsługuje C99, dlatego właśnie go brakuje.
+0

Moim zmartwieniem było, że gdybym na przykład zaktualizował Visual Studio i 'math.h', to uwzględniłbym' round() '- wtedy byłby konflikt taki jak w OSX. Dlatego uważałem, że lepszym rozwiązaniem byłoby sprawdzenie funkcji zamiast środowiska. To linia myślenia, którą posiadam od tworzenia stron internetowych, gdzie testuje się funkcje, zamiast wąchać ciąg znaków użytkownika. – thomthom

+0

@thomthom: Tak, ale to nie jest tworzenie stron WWW =). Tak właśnie to robisz. Czasami, gdy zmieniasz kompilatory, wszystko się psuje i musisz je naprawić, ale można tego uniknąć w większości przypadków. W tym przypadku słowo "round" zostało dodane w C99. VS nie obsługuje C99, dlatego nie jest obecny. –

+0

Autoconf GNU wykorzystuje podejście oparte na cechach, # definiowanie stałych w postaci 'HAVE_feature'. Na przykład możesz zdefiniować 'HAVE_ROUND'. Ponieważ w tym przypadku jest zależne od kompilatora, możesz zrobić "-DHAVE_ROUND = 0" w swoich definicjach preprocesora C w komendzie kompilacji; pozostaw to niezdefiniowane pod kompilatorami, które mają round(). Owijarka wokół twojej funkcji round() będzie czytać "#if zdefiniowane (HAVE_ROUND) &&! HAVE_ROUND ... deklaracja funkcji ... # endif". –

0

To, co zrobiłeś, to poprawny sposób radzenia sobie z niezgodnościami.

Zauważyłeś, że ten sposób radzenia sobie z niezgodnościami zależnymi od systemu jest "nietypowy", ale w przeciwieństwie do języków takich jak JAVA, który usuwa takie problemy, z którymi musisz sobie radzić. Z drugiej strony zawsze uzyskasz najlepszą wydajność, jaką oferuje platforma.

Powiązane problemy