सेगमेंट किए गए हेडर

J2ObjC से जनरेट की गई हेडर फ़ाइलों को सेगमेंट में बांटा जाता है और एक बार में एक सेगमेंट शामिल किया जा सकता है. अनुवाद किए गए हर Java टाइप के लिए एक सेगमेंट बनाया जाता है, ताकि हर अंदरूनी क्लास का अपना सेगमेंट हो. हेडर को शामिल करते समय, सिर्फ़ किसी खास सेगमेंट को पढ़ने के लिए, कॉम्पाइलर को बताने के लिए, प्रीप्रोसेसर मैक्रो का इस्तेमाल किया जाता है. सेगमेंट वाले हेडर, J2ObjC से जनरेट किए गए हेडर में शामिल साइकल की समस्या को हल करते हैं. इस बारे में इस दस्तावेज़ में पूरी जानकारी दी गई है.

आपके काम की जानकारी

  • J2ObjC से जनरेट किए गए हेडर शामिल करने के लिए, #import के बजाय #include का इस्तेमाल करें.
    • सेगमेंट वाले हेडर के साथ #import का इस्तेमाल करना समस्या पैदा करता है, क्योंकि अगर कंपाइलर को हेडर पहले से दिख चुका है, तो वह उसे पढ़ना छोड़ देगा. हालांकि, हेडर को सेगमेंट में बांटा गया है, इसलिए हो सकता है कि पहली बार कंपाइलर ने इसे पूरी तरह से पार्स न किया हो.
  • सेगमेंट वाले हेडर को --no-segmented-headers फ़्लैग की मदद से बंद किया जा सकता है.

सर्कुलर में ये शामिल हैं

J2ObjC से जनरेट की गई हेडर फ़ाइलों को, टाइप की ज़रूरी जानकारी को हल करने के लिए, शामिल करने और फ़ॉरवर्ड डिक्लेरेशन का इस्तेमाल करना चाहिए. फ़ॉरवर्ड डिक्लेरेशन का इस्तेमाल ज़्यादा से ज़्यादा किया जाता है. हालांकि, जिन टाइप को एक्सटेंड या लागू किया जा रहा है उनके लिए शामिल करना ज़रूरी है, क्योंकि कंपाइलर को टाइप के बारे में पूरी जानकारी की ज़रूरत होती है.

J2ObjC से जनरेट की गई हेडर फ़ाइलों में, शामिल किए जाने वाले साइकल जनरेट किए जा सकते हैं. ऐसा साइकल पाने के लिए, हमें फ़ाइल A में एक ऐसी क्लास चाहिए जो फ़ाइल B में मौजूद क्लास को एक्सटेंड करती हो. साथ ही, फ़ाइल B में एक ऐसी क्लास चाहिए जो फ़ाइल A में मौजूद क्लास को एक्सटेंड करती हो. ऐसा होने की संभावना कम है, लेकिन Guava के कोडबेस (और दूसरी जगहों) में ऐसा होता है.

इस समस्या को ठीक करने का एक आसान तरीका यह है कि .java फ़ाइल में मिले हर Java टाइप के लिए, एक अलग हेडर फ़ाइल जनरेट की जाए. हालांकि, J2ObjC को बाइल्ड टूल के तौर पर इस्तेमाल करने के लिए डिज़ाइन किया गया है. साथ ही, कोई भी अच्छा बाइल्ड सिस्टम, हर इनपुट के लिए अनुमानित आउटपुट पर निर्भर करता है. इसका मतलब है कि हर .java फ़ाइल से, एक .h और एक .m फ़ाइल बननी चाहिए.

उदाहरण

Foo.java:

class Foo extends Bar {}

Bar.java:

class Bar {
  static class Baz extends Foo {}
}

Foo.h (सेगमेंट में नहीं बांटा गया):

#ifndef _Foo_H_
#define _Foo_H_

#include "Bar.h"
#include "J2ObjC_header.h"

@interface Foo : Bar
- (instancetype)init;
@end

#endif // _Foo_H_

Bar.h (सेगमेंट में नहीं बांटा गया):

#ifndef _Bar_H_
#define _Bar_H_

#include "Foo.h"
#include "J2ObjC_header.h"

@interface Bar : NSObject
- (instancetype)init;
@end

@interface Bar_Baz : Foo
- (instancetype)init;
@end

#endif // _Bar_H_

ध्यान दें कि Foo.h में Bar.h शामिल है और Bar.h में Foo.h शामिल है. इस वजह से, ये हेडर कोड कंपाइल नहीं हो पाते:

../dist/j2objcc -c Foo.m
In file included from Foo.m:6:
In file included from ./Bar.h:9:
./Foo.h:12:18: error: cannot find interface declaration for 'Bar', superclass of 'Foo'
@interface Foo : Bar
~~~~~~~~~~~~~~   ^

Foo.h और Bar.h के सेगमेंट किए गए वर्शन, जो बिना किसी गड़बड़ी के कंपाइल हो जाएंगे:

Foo.h (सेगमेंट किया गया):

#include "J2ObjC_header.h"

#pragma push_macro("Foo_INCLUDE_ALL")
#if Foo_RESTRICT
#define Foo_INCLUDE_ALL 0
#else
#define Foo_INCLUDE_ALL 1
#endif
#undef Foo_RESTRICT

#if !defined (_Foo_) && (Foo_INCLUDE_ALL || Foo_INCLUDE)
#define _Foo_

#define Bar_RESTRICT 1
#define Bar_INCLUDE 1
#include "Bar.h"

@interface Foo : Bar
- (instancetype)init;
@end

#endif

#pragma pop_macro("Foo_INCLUDE_ALL")

Bar.h (सेगमेंट किया गया):

#include "J2ObjC_header.h"

#pragma push_macro("Bar_INCLUDE_ALL")
#if Bar_RESTRICT
#define Bar_INCLUDE_ALL 0
#else
#define Bar_INCLUDE_ALL 1
#endif
#undef Bar_RESTRICT

#if !defined (_Bar_) && (Bar_INCLUDE_ALL || Bar_INCLUDE)
#define _Bar_

@interface Bar : NSObject
- (instancetype)init;
@end

#endif

#if !defined (_Bar_Baz_) && (Bar_INCLUDE_ALL || Bar_Baz_INCLUDE)
#define _Bar_Baz_

#define Foo_RESTRICT 1
#define Foo_INCLUDE 1
#include "Foo.h"

@interface Bar_Baz : Foo
- (instancetype)init;
@end

#endif

#pragma pop_macro("Bar_INCLUDE_ALL")