Slice Metadata Directives
10 min read
8 min read
9 min read
7 min read
6 min read
5 min read
7 min read
5 min read
6 min read
Overview
A metadata directive gives the Slice compilers an instruction about a Slice definition or a Slice file. Most directives customize the code generated for one language mapping, and start with the prefix of this mapping, such as java::
["java:type:java.util.LinkedList<Integer>"] sequence<int> IntSeq;The general directives have no prefix. For example, format selects how Ice marshals class instances, and deprecated marks a definition as deprecated.
You place directives in square brackets before the definition they apply to, separated by commas or in consecutive lists, as in ["amd"]["deprecated"]:
["amd", "deprecated"]interface Greeter{ string greet(string name);}A file directive applies to a whole Slice file. You place it in double square brackets before any definition in this file; it can follow #include directives:
[["cpp:dll-export:WIDGET_API"]]Each directive applies only to certain kinds of definitions, listed in its description below.
General Metadata Directives
amd
["amd"]. Applies to interfaces and operations.
In C++, C#, and Java, the skeleton provides an asynchronous method for the operation, or for each operation of the interface, instead of a synchronous method. Instead of using this directive, you can also derive your servant class from the asynchronous skeleton; see Operations. The other Slice compilers ignore this directive.
deprecated
["deprecated"] or ["deprecated:message"]. Applies to interfaces, operations, classes, exceptions, structs, sequences, dictionaries, enumerations, enumerators, constants, and fields.
This directive marks a definition as deprecated; see Deprecating Slice Definitions.
format
["format:compact"] or ["format:sliced"]. Applies to interfaces and operations.
This directive selects the encoding format of the class instances marshaled as the arguments or result of an operation: format:compact selects the compact format, and format:sliced selects the sliced format. On an interface, it applies to all the operations of the interface; on an operation, it overrides the format directive of the enclosing interface.
When neither an operation nor its enclosing interface selects a format, the Ice.Default.SlicedFormat property selects it.
marshaled-result
["marshaled-result"]. Applies to interfaces and operations.
This directive lets a servant marshal the results of an operation as soon as it computes them, typically while it holds the lock that protects the data it returns. The mapped skeleton method returns a “marshaled result” struct or class whose constructor marshals the return value and out parameters immediately.
On an interface, this directive applies to every operation that the interface defines. The Slice compiler changes the mapping of an operation only when its return type or one of its out parameters is a class, struct, sequence, or dictionary. This directive affects the server-side mapping in C++, C#, and Java, and has no effect on the client-side mapping.
For example:
module M{ sequence<int> IntSeq; sequence<IntSeq> IntIntSeq; sequence<string> StringSeq;
class Grid { StringSeq xLabels; StringSeq yLabels; IntIntSeq values; }
interface GridIntf { // We want to marshal the returned Grid object within a lock, // and return a consistent object not affected by concurrent calls to // clearValues. ["marshaled-result"] ["cs:identifier:GetGrid"] Grid getGrid();
void clearValues(); }}The mapped skeleton member function for getGrid is:
GetGridMarshaledResult getGrid(const Ice::Current& current) = 0;where GetGridMarshaledResult is a generated class with a constructor that accepts a parameter for the return value, followed by Current:
// Generated server-side codeclass GetGridMarshaledResult : public Ice::MarshaledResult{public: // Marshals returnValue immediately. GetGridMarshaledResult(const GridPtr& returnValue, const Ice::Current& current);};A typical implementation of the getGrid operation in your servant would be:
GridServant::GetGridMarshaledResultGridServant::getGrid(const Ice::Current& current){ lock_guard lock(_mutex); // marshal _grid data member within synchronization return GetGridMarshaledResult{_grid, current};}The mapped skeleton method for getGrid is:
GridIntf_GetGridMarshaledResult GetGrid(Ice.Current current);where GridIntf_GetGridMarshaledResult is a generated record struct with a constructor that accepts a parameter for the return value, followed by Current:
// Generated server-side codepublic readonly record struct GridIntf_GetGridMarshaledResult : Ice.MarshaledResult{ // Marshals returnValue immediately. public GridIntf_GetGridMarshaledResult(Grid? ret, Ice.Current current) { ... } ...}A typical implementation of the getGrid operation in your servant would be:
public override GridIntf_GetGridMarshaledResult GetGrid(Ice.Current current){ lock (_mutex) { // marshal _grid field within synchronization return new GridIntf_GetGridMarshaledResult(_grid, current); }}The mapped skeleton method for getGrid is:
GridIntf.GetGridMarshaledResult getGrid(com.zeroc.Ice.Current current);where GetGridMarshaledResult is a nested static class with a constructor that accepts a parameter for the return value, followed by Current:
// Generated server-side codepublic interface GridIntf extends com.zeroc.Ice.Object { public static class GetGridMarshaledResult implements com.zeroc.Ice.MarshaledResult { public GetGridMarshaledResult( Grid returnValue, com.zeroc.Ice.Current current) { ... } } ...}A typical implementation of the getGrid operation in your servant would be:
@Overridepublic GridIntf.GetGridMarshaledResult getGrid(com.zeroc.Ice.Current current) { synchronized (_mutex) { // marshal _grid field within synchronization return new GridIntf.GetGridMarshaledResult(_grid, current); }}oneway
["oneway"]. Applies to operations.
This directive restricts an operation to oneway invocations. The operation cannot have a return type, out parameters, or an exception specification.
suppress-warning
[["suppress-warning"]] or [["suppress-warning:category, ..."]]. Applies to a Slice file.
This directive suppresses Slice compiler warnings for all the definitions in the Slice file. Without a category, it suppresses all warnings; with one or more categories, it suppresses only the warnings in these categories:
| Category | Description |
|---|---|
all | Suppress all Slice compiler warnings. Equivalent to [["suppress-warning"]]. |
deprecated | Suppress warnings related to deprecated features. |
invalid-comment | Suppress warnings related to invalid doc comments. |
Language-Specific Metadata Directives
C++ metadata directives use the cpp prefix.
cpp:array
["cpp:array"]. Applies to sequence parameters of operations.
This directive maps the parameter to a pair of pointers.
cpp:const
["cpp:const"]. Applies to operations.
This directive makes the pure virtual member function of the skeleton class const.
cpp:custom-print
["cpp:custom-print"]. Applies to enumerations, structs, classes, and exceptions.
This directive tells the Slice compiler that you implement the printing of this type yourself:
- For an enum
E, the Slice compiler declaresstd::ostream& operator<<(std::ostream&, E)in the enclosing namespace, but does not implement this operator. - For a struct
S, the Slice compiler declaresstd::ostream& operator<<(std::ostream&, const S&)in the enclosing namespace, but does not implement this operator. - For a class or exception, the Slice compiler declares the member function
void ice_print(std::ostream& os) const overridein the mapped C++ class, but does not implement this member function.
The default printing is described in Printing Enumerators, Printing Structs, Printing Classes, and Exception Printing.
cpp:dll-export
[["cpp:dll-export:SYMBOL"]]. Applies to a Slice file.
This directive exports the symbols of the generated code from a DLL (on Windows) or a shared library (on other platforms). The Slice compiler adds SYMBOL to the exported declarations. The generated header defines SYMBOL to export these declarations when SYMBOL_EXPORTS is defined, and to import them otherwise; the generated source file defines SYMBOL_EXPORTS.
cpp:doxygen
[["cpp:doxygen:include:header"]]. Applies to a Slice file.
This directive adds a doc comment with @headerfile and header to all generated C++ classes.
cpp:header-ext
[["cpp:header-ext:extension"]]. Applies to a Slice file.
This directive sets the file extension of the generated header file, instead of the default .h.
cpp:identifier
["cpp:identifier:name"]. Applies to any definition, parameter, or field.
The generated C++ code uses name instead of the Slice identifier. For example:
struct Descriptor{ ["cpp:identifier:blueprint"] string template;}The field template maps to blueprint in C++. The default mapping, template, is a C++ keyword.
cpp:ice_print
["cpp:ice_print"]. Applies to exceptions.
This directive is a deprecated alias for cpp:custom-print.
cpp:include
[["cpp:include:header"]]. Applies to a Slice file.
This directive adds #include <header> to the generated header file, typically for a type you select with cpp:type.
cpp:source-ext
[["cpp:source-ext:extension"]]. Applies to a Slice file.
This directive sets the file extension of the generated source file, instead of the default .cpp.
cpp:source-include
[["cpp:source-include:header"]]. Applies to a Slice file.
This directive adds #include <header> to the generated source file, for example when the generated code needs the complete definition of a type that the generated header does not include.
cpp:type
["cpp:type:type"]. Applies to sequences and dictionaries.
On a sequence or dictionary, or on a parameter or field of such a type, this directive maps it to the C++ type type.
cpp:type:string and cpp:type:wstring
["cpp:type:string"] or ["cpp:type:wstring"]. Applies to strings, and to modules, interfaces, classes, structs, and exceptions.
Slice strings map by default to std::string. cpp:type:wstring maps them to std::wstring instead, and cpp:type:string maps them back to std::string. On a module, interface, class, struct, or exception, these directives apply to all the strings it contains:
module A{ ["cpp:type:wstring"] struct Struct1 { string s1; // Maps to std::wstring ["cpp:type:string"] string s2; // Maps to std::string }}cpp:view-type
["cpp:view-type:type"]. Applies to sequence parameters of operations.
This directive maps the parameter to the C++ type type, a view that does not own the elements, where the generated code only reads the sequence, such as an in parameter of a proxy function.
C# metadata directives use the cs prefix.
cs:attribute
["cs:attribute:attribute"]. Applies to enumerations, enumerators, constants, and fields.
This directive adds the C# attribute attribute to the generated code. For example, ["cs:attribute:System.Flags"] on an enumeration adds [System.Flags] to the mapped C# enum.
cs:class
["cs:class"]. Applies to structs.
This directive maps the Slice struct to a C# class instead of a C# struct.
cs:generic
["cs:generic:type"]. Applies to sequences and dictionaries.
On a sequence, type is List, LinkedList, Queue, Stack, or a custom collection type; LinkedList, Queue, and Stack are not supported on a sequence of classes. On a dictionary, type is SortedDictionary or SortedList.
cs:identifier
["cs:identifier:name"]. Applies to any definition, parameter, or field.
The generated C# code uses name instead of the Slice identifier. For example:
interface Greeter{ ["cs:identifier:Greet"] string greet(string name);}The operation greet maps to the methods Greet and GreetAsync in C#, instead of greet and greetAsync.
cs:internal
["cs:internal"]. Applies to interfaces, classes, exceptions, structs, sequences, dictionaries, enumerations, and constants.
This directive makes the generated C# declarations internal instead of public.
cs:namespace
["cs:namespace:enclosing-namespace"]. Applies to top-level modules.
This deprecated directive nests the C# namespace of the module in enclosing-namespace: with ["cs:namespace:Acme"] on module Demo, the generated code is in the namespace Acme.Demo. Use cs:identifier instead.
cs:property
["cs:property"]. Applies to structs, classes, and exceptions.
This directive maps the Slice fields to C# properties instead of C# fields.
cs:readonly
["cs:readonly"]. Applies to structs.
When the Slice struct maps to a C# record struct, the mapped record struct is marked readonly.
When the Slice struct maps to a C# record class, the fields of this class are mapped to readonly C# fields or get-only properties (see cs:property), except for fields with a Slice class type that are mapped as usual (read-write fields or get-set properties).
Java metadata directives use the java prefix.
java:buffer
["java:buffer"]. Applies to sequences of byte, short, int, long, float, and double.
This directive maps the sequence to a subclass of java.nio.Buffer.
java:getset
["java:getset"]. Applies to fields, structs, classes, and exceptions.
This directive adds accessor and modifier methods (JavaBean methods) for fields.
java:identifier
["java:identifier:name"]. Applies to any definition, parameter, or field.
The generated Java code uses name instead of the Slice identifier. For example:
struct Descriptor{ ["java:identifier:ephemeral"] bool transient;}The field transient maps to ephemeral in Java. The default mapping, transient, is a Java keyword.
java:package
["java:package:enclosing-package"] or [["java:package:enclosing-package"]]. Applies to top-level modules and Slice files.
This deprecated directive nests the Java package of the module, or of every top-level module in the file, in enclosing-package: with ["java:package:com.acme"] on module Demo, the generated code is in the package com.acme.Demo. Use java:identifier on your modules instead.
java:serializable
["java:serializable:class"]. Applies to sequence<byte>.
This directive maps the sequence to class, the fully qualified name of a Java class that implements java.io.Serializable, so that you can transmit serializable Java objects without defining them in Slice. Ice transmits the Java serialization of the object as a sequence of bytes, which other language mappings receive as a plain byte sequence. See Filling a Sequence of Bytes with a Serializable Object for an example.
java:serialVersionUID
["java:serialVersionUID:uid"]. Applies to classes, exceptions, and structs.
The Slice-to-Java compiler computes a default value for the serialVersionUID field of the Java classes mapped from Slice classes, exceptions, and structs. This directive replaces this value with uid, an integer literal. The application is then responsible for updating the UID whenever changes to the Slice definition affect the serializable state of the type.
java:type
["java:type:instance-type"] or ["java:type:instance-type:formal-type"]. Applies to sequences and dictionaries.
This directive maps a sequence or dictionary to a custom Java type.
java:UserException
["java:UserException"]. Applies to operations.
The methods of the mapped servant interface and class declare throws com.zeroc.Ice.UserException, so they can throw any user exception, regardless of the exception specification of the Slice operation. This directive does not change the methods of the generated proxies.
JavaScript metadata directives use the js prefix.
js:defined-in
["js:defined-in:file"]. Applies to forward declarations of interfaces and classes.
This directive tells the Slice-to-JavaScript compiler which file to import the forward-declared type from in the TypeScript declarations; file is the relative path to the Slice file that defines the type. See Forward Declarations.
js:identifier
["js:identifier:name"]. Applies to any definition, parameter, or field.
The generated JavaScript code uses name instead of the Slice identifier. For example:
struct CompilerInfo{ ["js:identifier:debuggerName"] string debugger;}The field debugger maps to debuggerName. The default mapping, debugger, is a JavaScript keyword.
js:module
[["js:module:name"]]. Applies to a Slice file.
This directive tells the Slice-to-JavaScript compiler how other generated code imports the code generated for this file. It is mainly useful when you publish your generated code as an npm package, so that other projects can import the generated code for your Slice definitions by package name rather than by relative path.
For example, the Slice definitions for the Ice built-in files use:
// Ice/Locator.ice
[["js:module:@zeroc/ice"]]
#include "Identity.ice"
module Ice{ // ...}When you include Ice/Locator.ice in your own Slice files, the generated code imports Ice from @zeroc/ice. Without this directive, the compiler would instead generate a relative import, such as from Ice/Locator.js.
Files that use the same js:module directive import each other with relative paths, since they are assumed to be part of the same npm package.
MATLAB metadata directives use the matlab prefix.
matlab:identifier
["matlab:identifier:name"]. Applies to any definition, parameter, or field.
The generated MATLAB code uses name instead of the Slice identifier.
For example:
class AtmosphericConditions{ ["matlab:identifier:Temperature"] double temperature;
["matlab:identifier:Humidity"] double humidity;}The fields temperature and humidity map to the Temperature and Humidity properties in MATLAB.
Python metadata directives use the python prefix.
python:array.array
["python:array.array"]. Applies to sequences of bool, byte, short, int, long, float, and double.
This directive instructs the Ice for Python runtime to unmarshal the sequence as a Python array.array. See Python mapping for sequences.
python:identifier
["python:identifier:name"]. Applies to any definition, parameter, or field.
The generated Python code uses name instead of the Slice identifier. For example:
enum Color{ ["python:identifier:RED"] Red,
["python:identifier:GREEN"] Green,
["python:identifier:BLUE"] Blue}The enumerators Red, Green, and Blue map to RED, GREEN, and BLUE, per Python’s usual conventions, instead of the default mapping (Red, Green, and Blue).
python:list
["python:list"]. Applies to sequences.
This directive instructs the Ice for Python runtime to unmarshal the sequence as a list.
python:memoryview
["python:memoryview:factory"] or ["python:memoryview:factory:type-hint"]. Applies to sequences of bool, byte, short, int, long, float, and double.
This directive instructs the Ice for Python runtime to unmarshal the sequence as a custom Python type that the function factory creates from a Python memoryview object; type-hint is the type of the result in the generated type hints. See Python mapping for sequences.
python:numpy.ndarray
["python:numpy.ndarray"]. Applies to sequences of bool, byte, short, int, long, float, and double.
This directive instructs the Ice for Python runtime to unmarshal the sequence as a Python numpy.ndarray. See Python mapping for sequences.
python:tuple
["python:tuple"]. Applies to sequences.
This directive instructs the Ice for Python runtime to unmarshal the sequence as a Python tuple.
Swift metadata directives use the swift prefix.
swift:attribute
["swift:attribute:attribute"]. Applies to classes, structs, enumerations, and exceptions.
This directive adds the Swift attribute attribute to the generated code.
swift:identifier
["swift:identifier:name"]. Applies to any definition, parameter, or field.
The generated Swift code uses name instead of the Slice identifier. For example:
enum ButtonPressed{ ["swift:identifier:snooze"] Snooze,
["swift:identifier:stop"] Stop}The enumerators Snooze and Stop map to snooze and stop, per Swift’s usual conventions, instead of the default mapping (Snooze and Stop).
swift:module
["swift:module:module"] or ["swift:module:module:prefix"]. Applies to modules.
This deprecated directive maps the Slice module to the Swift module module, and gives all the Swift identifiers in this module the prefix prefix, as if they were defined in a nested Slice module prefix. Use swift:identifier instead.