To be able to follow the OSGi specification, a standard mapping from C to Java is defined. This mapping takes care of how instances, parameters, return values and error codes are used.
Before going into detail, here is an example of the mapping from a method in Java to a function in C:
celix_status_t bundleContext_getServiceReferences(BUNDLE_CONTEXT context, const char * serviceName, char * filter, ARRAY_LIST *service_references) :::java public ServiceReference getServiceReferences(String clazz, String filter) throws InvalidSyntaxException
Using the provided example, the following template can be extracted:
/** * celix_status_t: return type of the status code * * typeName: name of the object/type this function is part of * functionName: the name of the function * * typeName_t: The actual instance to "invoke" this function on * pool: optional pool on which the output is allocated * parameters: default function parameters * output parameters: the output which the caller can use */ celix_status_t typeName_functionName([typeName_t instance, ][apr_pool_t *pool, ][parameters, ][output parameters]);
To fully explain the mapping, the following items will be detailed:
- Instance parameter
- Error codes
- Output parameters
- Memory pools
When using Java, methods are related to an instance of a type. So for example, when the "getServiceReferences" method is used, it is always executed on an instance of BundleContext. When using C, functions are not related to any type, and as such, no instance information is available. To make this possible in Celix a pointer to the needed instance is always passed as first argument. The only exception are the "create" functions, they are used to create a new instance.
Furthermore, the instance typename is used as part of the function name, see "design.html" for more information.
The OSGi specification uses Java Exceptions for error handling. Even though there are Exceptions-like solutions for C, Celix uses the simpler approach. Every method in Celix returns an status code (celix_status_t), this code can be used for error handling.
Since the return value is always used for the status code output parameters are used to get a possible result from a function. Celix uses pass-by-reference for this, the uses has to supply a pointer to the function to get the results. Using this mechanism it is also possible to use multiple output parameters. Celix always uses the last parameter(s) for output, and the caller has to NULL-initialize the result field.
Celix uses APR memory pools for allocation. In the case a functions result has to be allocated to the caller its own pool, the pool has to be supplied as an parameter. Note: Not all of Celix' API have been updated to use APR (and memory pools), this is a work in progress.