Памятка по использованию Utils1s::Context
Средства Utils1s::Context представляют возможность создания переходников «класс C++ – контекст 1С». При этом происходит автоматическое преобразование массива параметров CValue в конкретные типы параметров (int, CString и т.д.) методов класса.
Пространство имен Utils1s::Context
Все классы переходника расположены в пространстве имен Utils1s::Context. Следующие классы используются конечным пользователем переходника:
TypeTraits – шаблонный класс характеристик некоторого типа. Для каждого используемого типа необходимо специализировать шаблон TypeTraits – определить правила, по которым происходит пребразование «тип» – CValue и обратно.
ContextDefinition – шаблонный класс характеристик некоторого класса C++ – для которого необходимо создать переходник в контекстный класс 1С. В классе определяются такие параметры контекста, как необходимость регистрации (возможность создавать через СоздатьОбъект), русскоязычное и англоязычное имя, определения методов и свойств класса.
CContext – собственно сам переходник – шаблонный класс, реализующий интерфейс CBLContext.
TypeTraits
Для преобразования используется следующая концепция. Значение CValue сначала преобразуется в некоторый промежуточный тип. Значение промежуточного типа пребразуется в конечный тип и передается в качестве параметра в метод конечного класса C++. Если у класса-хозяина есть возможность модификации значения параметра (передача по ссылке или указателю), то после вызова метода значение промежуточного типа (возможно, уже измененное) преобразуется обратно в CValue.
Например, если метод принимает значение типа std::string &, то значение CValue пребразуется в значение std::string, а затем при вызове метода, ему в качестве параметра передается ссылка на временное значение.
Итак, в специализации TypeTraits для нужного нам типа должны быть следующие члены:
- тип StoreType – определяет тип для временного значения.
- тип AllowEmpty – может принимать два значения: boost::true_type и boost::false_type. Тип определяет, разрешено ли пользователю контекста опускать параметры этого типа. Если разрешено, то при получении от 1С пустого CValue, для заполнения временного значения будет вызываться функция TypeTraits::GetEmptyValue. Например, для типа int * можно разрешить передачу пустых значений. В этом случае конечному методу будет передаваться NULL.
- тип ModifiableByHandler – принимает два значения: boost::true_type и boost::false_type. Тип определяет, может ли конечный метод изменить временное значение. Если может, то, после вызова метода, будет произведено преобразование промежуточного значения в CValue. Например, значения типа int передаются по значению и конечный метод не может их модифицировать. Поэтому для типа int ModifiableByHandler устанавливается в boost::false_type. Напротив, значения типа int & могут модифицироваться методом, поэтому ModifiableByHandler устанавливается в boost::true_type.
- метод FromCValue – статический метод, который пребразует CValue в значение типа StoreType.
- метод ToCValue – статический метод, который преобразует промежуточное значение в CValue.
- метод GetEmptyValue – статический метод, возвращающий пустое значение текущего типа. Метод необходимо определяеть, если пользователю разрешено передавать пустые параметры.
- метод StoreTypeToType – статический метод, преобразующий значение промежуточного типа в значение конечного типа. Например, если конечным типом является ссылка, то этот метод должен вернуть ссылку на промежуточное значение.
- метод TypeToStoreType – статический метод, обычно спользуемый в реализации свойств. Должен преобразовать значение конечного типа в значение промежуточного типа.
Пример.
В текущем варианте уже есть готовые специализации для ряда числовых типов, для строк (CString и std::string), для ссылок, указателей, ссылок и указателей на константы.
ContextDefinition
Шаблонный класс, который нужно специализировать для каждого класса, для которого нужно создать контекст. Члены класса:
- тип RegisterContext – принимает два значения: boost::true_type и boost::false_type. Тип определяет, следует ли регистрировать класс в 1С (следует ли разрешать создание класса через СоздатьОбъект).
- статическая функция InitContext – функция производит регистрацию всех методов и свойств, для которых нужно сгенерировать переходники. Регистрация производится при помощи вызовов статических методов класса CContext.
- статическая функция EngName – возвращает англоязычный идентификатор контекста.
- статическая функция RusName – возвращает русскоязычный идентификатор контекста.
Пример.
CContext
Класс-переходник, реализующий интерфейс CBLContext и вызывающий методы конечного класса C++. Содержит следующие статические методы:
- RegisterMethod – делает доступным метод конечного класса для вызовов из языка 1С. Принимает 3 параметра: русскоязычное название метода, англоязычное название метода и адрес метода.
- RegisterProp (вариант Getter/Setter) – принимает 4 параметра: русскоязычное название свойства, англоязычное название свойства, адрес геттера и адрес сеттера. В качестве адреса геттера или сеттера может быть передан NULL. При этом свойство станет только читаемым или только записываемым.
- RegisterProp (вариант прямого доступа к члену класса) – принимает 3 параметра: русскоязычное название свойства, англоязычное название свойства и адрес члена данных конечного класса. Данный метод позволяет строить переходники к обычным структурам, когда для чтения/модификации данных не используются геттеры/сеттеры, а используется прямой доступ к открытому члену данных.
Для взаимодействия с конечным классом CContext используется метод делегирования. Т.е. CContext ни является базовым классом для конечного класса, ни является его наследником. CContext содержит указатель на объект конечного класса и все вызовы производит через него. При этом CContext может единолично владеть объектом конечного класса, разделять владение с другими объектами или просто содержать указатель на конечный объект без управления его временем жизни. Поведение CContext определяется тем, как он был сконструирован.
Если для создания был использован конструктор без параметров, то CContext автоматически создает объект конечного класса и разрушает его при собственном разрушении. При этом можно использовать метод GetMainPtr для получения указателя boost::shared_ptr на объект конечного класса.
Если для создания был использован конструктор, принимающий shared_ptr, то CContext не будет создавать новый объект, а будет разделять владение объектом конечного класса с другими объектами. При этом по прежнему доступен метод GetMainPtr.
Если для создания был использован конструктор, принимающий обычный указатель на объект конечного класса, то CContext не будет ни создавать объект конечного класса, ни удалять его при собственном разрушении.
Всегда у объекта типа CContext доступна функция GetMain возвращающая обычный указатель на объект конечного класса.
Чтобы компилятор сгенерировал контекст для нужного нам класса, необходимо после определения ContextDefinition вставить запрос на явное инстанцирование шаблона CContext для конечного класса:
Пример определения контекстного класса:
В этом примере определяется контекстный переходник для обычного MFC-класса CFont. Разрешается создание объектов через СоздатьОбъект по имени Michele::CFont.
Также вводятся правила преобразования значений типа CFont * в CValue и обратно. Для этого используется вспомогательный класс ContextTraits, который при необходимости преобразовать CFont * в CValue будет создавать CContext<CFont> и передавать его в 1С. А при преобразовании из CValue класс будет пытаться пребразовать CBLContext в CContext<CFont>, чтобы далее вызвать у него метод GetMain.
Страницы, ссылающиеся на данную:
HomePage