Руководство разработчика на IDL
Правила и синтаксис
XPIDL (XP1 Interface
Description Language - Кросплатформенный язык описания
интерфейсов) основан на спецификации OMG IDL, который используется для описания
интерфейсов CORBA. XPIDL не является ни строгим подмножеством ни строгим
расширением OMG IDL, поскольку в него включен некоторый специфичный для XPCOM
синтаксис, при том что поддерживаются не все синтаксические конструкции OMG IDL.
Этот раздел посвящен правилам XPIDL для описания интерфейсов. Посмотреть код
C++, сгенерированный для данных здесь примеров, можно
здесь.
Интерфейсы
Интерфейс объявляется с помощью ключевого слова interface. Ниже
приведен простейший возможный интерфейс
(код
C++):
interface nsIFoo {
};
Для указания родительского интерфейса, его имя должно быть написано после
имени определяемого интерфейса и двоеточия
(код
C++):
interface nsIFoo : nsIParent {
};
В XPCOM все интерфейсы имеют сопоставленный IID. Используйте синтаксис
идентификационного атрибута для указания свойства uuid
(код
C++):
[uuid(00000000-0000-0000-c000-000000000046)]
interface nsIFoo : nsIParent {
};
Если вам нужна опережающая декларация интерфейса, просто опустите определение
интерфейса, все данные о родителе и свойства
(код
C++):
interface nsIForward;
Методы и свойства
Интерфейс может иметь как методы, так и свойства. Свойства являются
атрибутами объектов интерфейса, которые могут быть прочитаны и, возможно,
установлены в некоторое значение. Ниже приводится интерфейс с одним методом (не
имеищим параметров и не возвращающий значений), названным fun, и с
целочисленным свойством, названным attr
(код
C++):
interface nsIFoo {
attribute long attr;
void fun();
};
Методы могут иметь любое число in-, out- и
inout-параметров различных типов. Следующий
интерфейс демонстрирует различные "in-out-ness"2
параметры различных типов
(код
C++):
interface nsIStringStuff {
void findStringLength(in string str, out long l);
void concatenateStrings(in string str1, in string str2,
out string result);
void replaceChar(inout string str, in char from, in char to,
in boolean foldCase);
};
Вы можете указать возвращаемый тип для своего метода, отличный от
void, но вы должны знать о правилах генерации кода. Возвращаемый
не-void тип преобразуется в сгенерированном коде C++ в изменяемый
параметр (out)
(код
C++):
interface nsINonVoidReturn {
string gimmeString(in string str, in long count);
long gimmeLong(in boolean prime);
};
Свойства могут быть объявлены как "только для чтения" с помощью ключевого
слова readonly в определении
(код
C++):
interface nsIThing {
readonly attribute string lookButDontTouch;
};
В C++ для атрибутов интерфейса автоматически декларируются методы
Get и Set. Для атрибута с названием foo будут
сгенерированы методы доступа GetFoo и SetFoo. Заметьте, что в
названиях методов доступа первая буква названия атрибута была переведена в
верхний регистр.
Код XPIDL |
Генерируемый заголовок C++ |
interface nsIBar {
attribute short foo;
};
|
/* начало интерфейса: nsIBar */
class nsIBar : {
public:
/* attribute short foo; */
NS_IMETHOD GetFoo(PRInt16 *aFoo) = 0;
NS_IMETHOD SetFoo(PRInt16 aFoo) = 0;
};
|
Компилятор xpidl капитализирует названия методов в генерируемых заголовках
C++. Это делается для поддержки существующих в Mozilla соглашений по C++,
которые предусматривают ВерблюжачьюНотацию для названий методов. В JavaScript'е
названия методов будут иметь ту же самую капитализацию, какая была использована
в XPIDL. Согласно соглашениям, описанным в
устоявшейся
практике, названия методов в JavaScript следует писать в
верблюжачейНотации.
Код XPIDL |
Генерируемый заголовок C++ |
interface nsISil {
void twiddleSil();
};
|
/* начало интерфейса: nsISil */
class nsISil {
public:
/* void twiddleSil (); */
NS_IMETHOD TwiddleSil(void) = 0;
};
|
Если по какой то причине умолчальное название для метода или свойства не
может быть использованно, например, если название конфликтует с виндовым
макросом, то может быть использован модификатор
binaryname(Название) , который изменит конфликтное название в коде
C++. Например:
Код XPIDL |
Генерируемый заголовок C++ |
interface nsINameConflicts {
[binaryname(MessageMoz)] attribute AString message;
[binaryname(PostMessageMoz)] void postMessage(in AString message);
};
|
/* начало интерфейса: nsINameConflicts */
class nsINameConflicts {
public:
/* [binaryname(MessageMoz)] attribute AString message; */
NS_IMETHOD GetMessageMoz(nsAString& message) = 0;
NS_IMETHOD SetMessageMoz(const nsAString& message) = 0;
/* [binaryname(PostMessageMoz)] void postMessage(in AString message); */
NS_IMETHOD PostMessageMoz(const nsAString& message) = 0;
};
|
Предоопределенные типы
XPIDL предоставляет несколько предопределенных типов. Но могут использоваться
и нативные типы, хотя это ограничивает возможность
скриптования.
Тип |
Соответствие в C++ |
void |
void |
boolean |
PRBool |
octet |
PRUint8 |
short |
PRInt16 |
long |
PRInt32 |
long long |
PRInt64 |
unsigned short |
PRUint16 |
unsigned long |
PRUint32 |
unsigned long long |
PRUint64 |
float |
float |
double |
double |
char |
char |
wchar |
PRUnichar |
string |
char* |
wstring |
PRUnichar* |
Использование нативных типов
XPIDL позволяет использовать нативные типы, указанные с помощью декларации
native, которая работает аналогично конструкции typedef в
C++.
Нативный тип может быть задан именем с помощью следующего синтаксиса:
native name(native_type);
Возможно определить и типы ссылок и указателей, комбинируя [ref] или
[ptr] с native:
Код XPIDL |
Генерируемый для C++ |
[ref] native nsNativeFileRef(nsFileSpec);
[ptr] native nsNativeFilePtr(nsFileSpec);
interface foo {
void openByRef(in nsNativeFileRef aFileSpecRef);
void openByPtr(in nsNativeFilePtr aFileSpecPtr);
};
|
/* начало интерфейса: foo */
class foo {
public:
/* void openByRef (in nsNativeFileRef aFileSpecRef); */
NS_IMETHOD OpenByRef(nsFileSpec & aFileSpecRef) = 0;
/* void openByPtr (in nsNativeFilePtr aFileSpecPtr); */
NS_IMETHOD OpenByPtr(nsFileSpec * aFileSpecPtr) = 0;
};
|
Использование в вашем коде нативных типов может быть полезно для
переносимости существующих интерфейсов. Однако, использование нативных типов в
методе делает
этот метод недоступным из скриптов.
#include
Если вы ссылаетесь на интерфейсы, описанные в других файлах, то должны
подключать их следующим способом: #include "имяфайла.idl". В XPIDL
конструкция #include включает указанный файл только единожды. Поэтому
нет нужды защищать конструкцию #include с помощью ifdef, как
это делается в случае препроцессора C.
Перечисления и константы
Перечисления в стиле C не поддерживаются, поскольку размер перечислений может
зависеть от компилятора. Вместо этого XPIDL поддерживает определения констант,
которые становятся доступными как в C++ так и в JavaScript. Константы должны
иметь тип short или long и должны объявляться внутри описаний
интерфейсов.
Константы других типов не поддерживаются, поскольку не имеют аналогов в
других языках либо требуют значительных издержек по управлению памятью. Вместо
определения "constant", не являющегося типа short или long,
пишите метод, возвращающий нужное значение, или положите это значение в
атрибут.
Код XPIDL |
Код C++ |
const short c1 = 1+1; |
enum { c1 = 2 }; |
const short c2 = c1 * 5; |
enum { c2 = 10 }; |
const long flag = 1 << 5; |
enum { flag = 32 }; |
const float invalid_constant = 6.0; |
Предупреждение: проигнорировано объявление константы
'invalid_constant', тип которой не был "short" или "long". |
[Правила и синтаксис]
[Устоявшаяся
практика]
[Ключевые слова]
1: "XP", конечно же, означает "cross-platform"
(кросплатформеный).
2: Я хочу лучшего названия для этого.
Mike Shaver
Mike Ang
Mike McCabe
Перевод: Д. Скоробогатов (08.10.2009)
Оригинальный текст:
IDL Author's Guide - Rules and Syntax
Последнее редактирование: 2009-10-12 16:50:12
Метки материала:
XPIDL, XPCOM, языки программирования, C++, язык описаниния интерфейсов, файлы интерфейсов, синтаксис, правила, language, Interface Description Language, interface, компонентная объектная модель, syntax, OMG IDL, IDL, Component Object Model, интерфейсы
Оставьте, пожалуйста, свой комментарий к публикации
|