The mapping of OMG IDL to the C programming language when C Server switch is the back-end of choice is identical to the one use in C IDL mappning. The only difference is on the generated code, and that the idl functions are translated to C function calls for the C Server.
The C-server uses the same communication protocol as for the Erlang genservers, it is actually a C-genserver. So the C-server can be used for :
The code produced is a collection of :
< Scoped Interface Name >__s.c
convensionAll functions found in the code are exported. The user is free to define his own switches if there is a need for this.
The main functionality of a C server switch is to :
cast
)The C source defines the following functions :
The interface for the server switch is :
int < Scoped Interface Name >__switch(< Interface Object > oe_obj, CORBA_Environment *oe_env );
Where :
< Interface Object > oe_obj
is the client interface object.
CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
int
which is positive or zero when the call is succesful,
negative otherwiseThe interface for the generic message decoder is :
int < Scoped Interface Name >__call_info((< Interface Object > oe_obj, CORBA_Environment *oe_env );
Where :
< Interface Object > oe_obj
is the client interface object.
CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
int
which is positive or zero when the call is succesful,
negative otherwiseThe interface for the specific call function definition is :
int < Scoped Function Name >__exec(< Interface Object > oe_obj, CORBA_Environment *oe_env );
Where :
< Interface Object > oe_obj
is the client interface object.
CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
int
which is positive or zero when the call is succesful,
negative otherwiseThe interface for the specific parameter decoder function is :
int < Scoped Function Name >__dec( < Interface Object > oe_obj, < Parameters > CORBA_Environment *oe_env );
Where :
< Interface Object > oe_obj
is the client interface object.
< Parameters >
are pointers to parameters for the function call to be decoded.
The order of apearence is similar to the IDL definition of the function.CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
int
which is positive or zero when the call is succeed,
negative otherwizeThe interface for the specific callback function is :
< Scoped Function Name >__rs* < Scoped Function Name >__cb( < Interface Object > oe_obj, < Parameters > CORBA_Environment *oe_env );
Where :
< Interface Object > oe_obj
is the client interface object.
< Parameters >
are pointers to in/out-parameters for the function call.
The order of apearence is similar to the IDL definition of the function.CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
pointer to the restore function
which is NULL when the restore function is
not defined, initiated to point the restore function otherwiseCallback functions are implementation dependent and in order to make things work, the following rule must be followed when passing arguments to callback functions :
in
parameters of variable storage type are passed as is.
out
parameters of variable storage type are passed by a pointer to their value.
in / out
parameters of fixed storage type are passed by a pointer to their value.
return
values are always passed by a pointer to their value.
The interface for the specific message encoder function is :
int < Scoped Function Name >__enc( < Interface Object > oe_obj, < Parameters > CORBA_Environment *oe_env );
Where :
< Interface Object > oe_obj
is the client interface object.
< Parameters >
are pointers to parameters for the return message to be encoded.
The order of appearence is similar to the IDL definition of the function.CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
int
which is positive or zero when the call is successful,
negative otherwizeThe encoder function is generated only for usual call IDL-functions (not oneways)
The interface for the specific restore function is :
void < Scoped Function Name >__rs( < Interface Object > oe_obj, < Parameters > CORBA_Environment *oe_env );
Where :
< Interface Object > oe_obj
is the client interface object.
< pointers to result values / parameters >
are pointers to in/out-parameters for the function call.
The order of appearence is similar to the IDL definition of the function.CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
The restore function type definition is recorded on the interface header file. It is unique for each IDL defined interface function
Depending on the data defined and used in the IDL code, C-source files may be generated that hold functions used internally. This is the case when other types than the elementary IDL types are used by the IDL file definitions. All these files must be compiled and linked to the other code.
The only header files that must be included are the interface files, the files named < Scoped Interface Name >__s.h
Under compilation you will have to include :
$OTPROOT/ usr/ include
Under linking you will have to link with :
$OTPROOT/ usr/ lib
In the Erlang shell type :
ic:gen(<filename>, [{be, c_server}])
.
For each IDL interface <interface name>
defined in the IDL file :
For each function defined in the IDL interface :
In this example, a file "random.idl" generates code for the plain erlang back-end :
module rmod { interface random { double produce(); oneway void init(in long seed1, in long seed2, in long seed3); }; };
Compile the file :
Erlang (BEAM) emulator version 4.9 Eshell V4.9 (abort with ^G) 1> ic:gen(random,[{be, c_server}]). Erlang IDL compiler version 3.2 ok 2>
When the file "random.idl" is compiled it produces five files, two for
the top scope, two for the interface scope, and one for the module
scope. The header files for top scope and interface
are empty and not shown here. In this case only the file for the interface
rmod_random.erl
is important :.
#include <string.h> #include "ic.h" #include "erl_interface.h" #include "ei.h" #include "rmod_random__s.h" /* * Main switch */ int rmod_random__switch(rmod_random oe_obj, CORBA_Environment *oe_env) { int status=0; /* Initiating exception indicator */ oe_env->_major = CORBA_NO_EXCEPTION; /* Call switch */ if ((status = rmod_random__call_info(oe_obj, oe_env)) >= 0) { if (strcmp(oe_env->_operation, "produce") == 0) return rmod_random_produce__exec(oe_obj, oe_env); if (strcmp(oe_env->_operation, "init") == 0) return rmod_random_init__exec(oe_obj, oe_env); /* Bad call */ CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_OPERATION, "Invalid operation"); return -1; } /* Exit */ return status; } /* * Returns call identity */ int rmod_random__call_info(rmod_random oe_obj, CORBA_Environment *oe_env) { char gencall_atom[10]; int error_code = 0; int rec_version = 0; oe_env->_iin = 0; oe_env->_received = 0; ei_decode_version(oe_env->_inbuf, &oe_env->_iin, &rec_version); ei_decode_tuple_header(oe_env->_inbuf, &oe_env->_iin, &oe_env->_received); ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, gencall_atom); if (strcmp(gencall_atom, "$gen_cast") == 0) { if ((error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_env->_operation)) < 0) { ei_decode_tuple_header(oe_env->_inbuf, &oe_env->_iin, &oe_env->_received); if ((error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_env->_operation)) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_OPERATION, "Bad Message, cannot extract operation"); return error_code; } oe_env->_received -= 1; } else oe_env->_received -= 2; return 0; } if (strcmp(gencall_atom, "$gen_call") == 0) { ei_decode_tuple_header(oe_env->_inbuf, &oe_env->_iin, &oe_env->_received); if ((error_code = ei_decode_pid(oe_env->_inbuf, &oe_env->_iin, &oe_env->_caller)) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Bad Message, bad caller identity"); return error_code; } if ((error_code = ei_decode_ref(oe_env->_inbuf, &oe_env->_iin, &oe_env->_unique)) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Bad Message, bad message reference"); return error_code; } if ((error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_env->_operation)) < 0) { ei_decode_tuple_header(oe_env->_inbuf, &oe_env->_iin, &oe_env->_received); if ((error_code = ei_decode_atom(oe_env->_inbuf, &oe_env->_iin, oe_env->_operation)) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_OPERATION, "Bad Message, cannot extract operation"); return error_code; } oe_env->_received -= 1; return 0; } else { oe_env->_received -= 2; return 0; } } CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Bad message, neither cast nor call"); return -1; } int rmod_random_produce__exec(rmod_random oe_obj, CORBA_Environment *oe_env) { if (oe_env->_received != 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_PARAM, "Wrong number of operation parameters"); return -1; } else { rmod_random_produce__rs* oe_restore = NULL; CORBA_double oe_result = 0; /* Callback function call */ oe_restore = rmod_random_produce__cb(oe_obj, &oe_result, oe_env); /* Encoding reply message */ rmod_random_produce__enc(oe_obj, oe_result, oe_env); /* Restore function call */ if (oe_restore != NULL) (*oe_restore)(oe_obj, &oe_result, oe_env); } return 0; } int rmod_random_produce__enc(rmod_random oe_obj, CORBA_double oe_result, CORBA_Environment *oe_env) { int oe_error_code; oe_env->_iout = 0; oe_ei_encode_version(oe_env); oe_ei_encode_tuple_header(oe_env, 2); oe_ei_encode_ref(oe_env, &oe_env->_unique); /* Encode parameter: CORBA_double oe_result */ if ((oe_error_code = oe_ei_encode_double(oe_env, oe_result)) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_PARAM, "Bad operation parameter on encode"); return oe_error_code; } return 0; } int rmod_random_init__exec(rmod_random oe_obj, CORBA_Environment *oe_env) { if (oe_env->_received != 3) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_PARAM, "Wrong number of operation parameters"); return -1; } else { int oe_error_code = 0; rmod_random_init__rs* oe_restore = NULL; CORBA_long seed1; CORBA_long seed2; CORBA_long seed3; /* Decode parameters */ if((oe_error_code = rmod_random_init__dec(oe_obj, &seed1, &seed2, &seed3, oe_env)) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, BAD_PARAM, "Bad parameter on decode"); return oe_error_code; } /* Callback function call */ oe_restore = rmod_random_init__cb(oe_obj, &seed1, &seed2, &seed3, oe_env); /* Restore function call */ if (oe_restore != NULL) (*oe_restore)(oe_obj, &seed1, &seed2, &seed3, oe_env); } return 0; } int rmod_random_init__dec(rmod_random oe_obj, CORBA_long* seed1, CORBA_long* seed2, CORBA_long* seed3, CORBA_Environment *oe_env) { int oe_error_code; if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, seed1)) < 0) return oe_error_code; if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, seed2)) < 0) return oe_error_code; if ((oe_error_code = ei_decode_long(oe_env->_inbuf, &oe_env->_iin, seed3)) < 0) return oe_error_code; return 0; }
The implementation file must be a C file, in this example we use a file called callbacks.c
.
This file must be implemented in a similar way :
#include <stdlib.h> #include "rmod_random__s.h" rmod_random_produce__rs* rmod_random_produce__cb(rmod_random oe_obj, double *rs, CORBA_Environment *oe_env) { *rs = (double) rand(); return (rmod_random_produce__rs*) NULL; } rmod_random_init__rs* rmod_random_init__cb(rmod_random oe_obj, long* seed1, long* seed2, long* seed3, CORBA_Environment *oe_env) { srand(*seed1 * *seed2 * *seed3); return (rmod_random_init__rs*) NULL; }
Compiling the Code :
![]() |
Due to changes inErl_Interface, to allow buffer expansion, a new receiving function
|
Running the example :