رؤوس مجزأة

تنقسم ملفات العناوين التي تم إنشاؤها بواسطة J2ObjC إلى شرائح، ويمكن تضمينها في مقطع واحد في كل مرة. ويتم إنشاء مقطع واحد لكل نوع لغة مترجم من نوع Java، بحيث يكون لكل فئة داخلية قطاع خاص بها. تُستخدم وحدات الماكرو للمعالجات المسبقة لتخبر المحول البرمجي بقراءة مقطع معيّن فقط عند تضمين العنوان.تحل العناوين المقسّمة مشكلة دورات التضمين في العناوين التي ينشئها J2ObjC، الموضّحة بالتفصيل أدناه.

ما تحتاج إلى معرفته

  • يمكنك استخدام #include بدلاً من #import لتضمين العناوين التي تم إنشاؤها باستخدام J2ObjC.
    • يؤدي استخدام #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_

بار. (غير مقسم):

#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")

البركة (مقسّمة):

#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")