2010-06-13 26 views
7

Heads up: Bu garip bir soru.Koşullu makro genişletme

Bazı günlük kayıtlarını kolaylaştırmak için kullanmak istediğim bazı yararlı makrolarım var. Örneğin, yapabilirim ve bu, self, _cmd, __FILE__, __LINE__, vb. Gibi şeyleri içeren daha karmaşık bir yöntem çağırma işlemine genişletilir, böylece işlerin nereden kaydedildiğini kolayca takip edebilirim. Bu harika çalışıyor.

Artık makrolarımı yalnızca Objective-C yöntemleriyle değil genel C işlevleriyle çalışmak üzere genişletmek istiyorum. Sorun, makro genişletmede bulunan self ve _cmd bölümleridir. Bu iki parametre C fonksiyonlarında mevcut değildir. İdeal olarak, bu aynı makro setini C fonksiyonları içerisinde kullanmak isterdim, ama problemlerle karşılaşıyorum. (Örneğin) Log() makrosunu kullandığımda, self ve _cmd ile ilgili derleyici uyarıları alıyorum (bu, toplam anlam ifade eder).

ilk düşüncem şu (benim makroda) böyle bir şey yapmak vardı:

if (thisFunctionIsACFunction) { 
    DoLogging(nil, nil, format, ##__VA_ARGS__); 
} else { 
    DoLogging(self, _cmd, format, ##__VA_ARGS__); 
} 

Tüm bu takdirde() ifadesi ile sonuçlanır makro yerine ikame edilir çünkü hala derleyici uyarıları üretir self ve _cmd anahtar sözcükleriyle ilgili hatalar (işlev yürütme sırasında hiçbir zaman çalıştırılmayacak olsalar bile).

Benim sonraki düşünce (benim makroda) Böyle bir şey yapmak için oldu:

if (thisFunctionIsACFunction) { 
    #define SELF nil 
    #define CMD nil 
} else { 
    #define SELF self 
    #define CMD _cmd 
} 
DoLogging(SELF, CMD, format, ##__VA_ARGS__); 

maalesef çalışmıyor Yani. İlk #define benim "hata: '#' bir makro parametresi tarafından takip edilmez" alıyorum.

Diğer düşüncem özellikle C işlevlerinde kullanılmak üzere ikinci bir grup makro oluşturmaktı. Bu kötü bir kod kokuyor ve ben gerçekten bunu yapmak istemiyorum.

Makro, bir Objective-C yönteminde bulunuyorsa, aynı makro kümesini hem Objective-C yöntemlerinde hem de C işlevlerinden ve yalnızca self ve _cmd referanslarından kullanmanın bir yolu var mı?

düzenlemek fazla bilgi:

thisFunctionIsACFunction oldukça ilkel bir şekilde tespit edilir (ve iyileştirmeler ve önerilere kesinlikle açığım). Temelde o da şu: başa ekleyerek derleyici davranışa dayanarak oluyor

BOOL thisFunctionIsACFunction == (__PRETTY_FUNCTION__[0] != '-' && __PRETTY_FUNCTION__[0] != '+'); 

bir '-' veya '+' Objective-C nesnelere örnek ve sınıf yöntemleri için. Başka bir şey bir C işlevi olmalıdır (çünkü C işlevleri '-' veya '+' ile başlayan adlara sahip olamaz).

__PRETTY_FUNCTION__'un bir char* ile değiştirilmesinden dolayı bu denetimin bir çalışma zamanı denetimi olduğunu anlıyorum ve bu muhtemelen yardım isteğim için ana yol barikatıdır.

+0

kullanabilir? – Artelius

+0

@Artelius daha fazla bilgi için soru düzenledi –

cevap

7

Önişlemci, gerçek kod ayrılmadan önce tüm çalışmalarını gerçekleştirir. Önişlemci , bir işlev C veya obj-C olup olmadığından kodun ayrıştırılmasından önce çalıştığı için olamaz. Aynı nedenle

,
if (thisFunctionIsACFunction) { 
    #define SELF nil 
    #define CMD nil 
} else { 
    #define SELF self 
    #define CMD _cmd 
} 
DoLogging(SELF, CMD, format, ##__VA_ARGS__); 

çalışamaz - # tanımlar derleme aşamasında önce işlenir. Bu nedenle, kodun kendisi bir "çalışma zamanı" denetimi içermelidir (ancak derleyici bunu optimize edebilir).

Ben

küresel kapsamda
void *self = nil; //not sure about the types that 
SEL _cmd = nil; //would be valid for obj-c 

gibi bir şey tanımlayan öneririm; C işlevleri bu tanımları "görecek", Objective-C yöntemleri ise kendi tanımları ile onları gizleyecektir.

+0

+1 Ha! Sen bir dahisin! Küresel düzeyde “self” ve “_cmd” yi tanımlamayı düşünmemiştim! Teşekkürler! (Ve mükemmel çalışıyor, sadece denedim.) –

0

Makro koşullu çeşit kullanabilirsiniz:

#ifndef OBJECTIVE_C 
    #define self 0 
    #define _cmd "" 
#endif 

Ben size self ve _cmd tanımlamak gerektiğini tam emin değilim, o sadece tahmin edildi.

Önceden tanımlanmış bir makro olup olmadığından emin değilim, çünkü C nesnesinde derleme yapıp yapmadığınızı kontrol edebilirsiniz, böylece yapınızın bir parçası olarak el ile OBJECTIVE_C tanımlamanız gerekebilir.

+0

İyi fikir. Tek sorun, Objective-C'nin C'nin katı bir üst kümesi olması, bu da ObjC ve C'nin yan yana barış içinde bir arada bulunabileceği anlamına geliyor. Bu, C işlevlerimin çoğunun '__OBJC__' # tanımlanmış olacağı anlamına gelir. –

1

Sen `thisFunctionIsACFunction` nasıl oluşturdunuz yok

if defined "abc" <statement1> 
else if defined "def" <statement2>