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 used in C IDL mapping. The only difference is on the generated code, and that the idl functions are translated to C functions for the C client.
A C-client uses the same communication protocol as an Erlang client to genservers, as it is actually a C-genserver client. Therefore, the C-client can be used for:
The code produced is a collection of:
< Scoped Interface Name >s.c
conventionAll functions found in the code are exported. The user is free to define
his own client if there is a need for this. The basic client generated
is a synchronous
client, but an asynchronous
client can be
implemented by proper use of exported functions.
The main functionality of a C client is to:
The C source defines the following functions:
The interface for the client function is:
< Return Value > < Scoped Function Name > ( < Interface Object > oe_obj, < Parameters > CORBA_Environment *oe_env );
Where:
< Return Value >
is the return value is the value to be returned as defined by the
IDL specification for the operation.
< Interface Object > oe_obj
is the client interface object.
< Parameters >
are the parameters to the operation in the same order as defined by the
IDL specdication for the operation.
CORBA_Environment *oe_env
is a pointer to the current client environment as described in section 3.6.
The interface for the message encoding functions is:
int < Scoped Function Name >__client_enc(< Interface Object > oe_obj, < Input Parameters > CORBA_Environment *oe_env );
Where:
< Interface Object > oe_obj
is the client interface object.
< Input Parameters >
are all the input
parameters to the operation in the same order as defined
by the IDL specification for the operation.
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 otherwiseThe interface for the specific result value decoder is:
int < Scoped Function Name >__client_dec(< Interface Object > oe_obj, < Return/Out Values > CORBA_Environment *oe_env);
Where:
< Interface Object > oe_obj
is the client interface object.
< Return/Out Values >
are return values in order similar to the IDL defined function's.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 otherwiseThe interface for the generic decoding function is:
int < Scoped Interface Name >__receive_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 succeed,
negative otherwiseDepending 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 :
< Scoped Interface Name >.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_client}])
.
In this example, a file "random.idl" is 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_client}]). 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 <stdlib.h> #include <string.h> #include "ic.h" #include "erl_interface.h" #include "ei.h" #include "rmod_random.h" /* * Object interface function "rmod_random_produce" */ CORBA_double rmod_random_produce(rmod_random oe_obj, CORBA_Environment *oe_env) { CORBA_double oe_result; int oe_msgType = 0; erlang_msg oe_msg; /* Initiating the message reference */ strcpy(oe_env->_unique.node,erl_thisnodename()); oe_env->_unique.creation = erl_thiscreation(); oe_env->_unique.id = 0; /* Initiating exception indicator */ oe_env->_major = CORBA_NO_EXCEPTION; /* Creating call message */ if (rmod_random_produce__client_enc(oe_obj, oe_env) < 0) { if (oe_env->_major == CORBA_NO_EXCEPTION) CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Cannot encode message"); return oe_result; } /* Sending call request */ if (strlen(oe_env->_regname) == 0) { if (ei_send_encoded(oe_env->_fd, oe_env->_to_pid, oe_env->_outbuf, oe_env->_iout) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE, "Cannot connect to server"); return oe_result; } } else if (ei_send_reg_encoded(oe_env->_fd, oe_env->_from_pid, oe_env->_regname, oe_env->_outbuf, oe_env->_iout) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE, "Cannot connect to server"); return oe_result; } /* Receiving reply message */ do { if ((oe_msgType = ei_receive_encoded(oe_env->_fd, &oe_env->_inbuf, &oe_env->_inbufsz, &oe_msg, &oe_env->_iin)) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Cannot decode message"); return oe_result; } } while (oe_msgType != ERL_SEND && oe_msgType != ERL_REG_SEND); /* Extracting message header */ if (rmod_random__receive_info(oe_obj, oe_env) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Bad message"); return oe_result; } /* Extracting return value(s) */ if (rmod_random_produce__client_dec(oe_obj, &oe_result, oe_env) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, DATA_CONVERSION, "Bad return/out value(s)"); } return oe_result; } /* * Encodes the function call for "rmod_random_produce" */ int rmod_random_produce__client_enc(rmod_random oe_obj, CORBA_Environment *oe_env) { int oe_error_code = 0; oe_env->_iout = 0; oe_ei_encode_version(oe_env); oe_ei_encode_tuple_header(oe_env, 3); oe_ei_encode_atom(oe_env, "$gen_call"); oe_ei_encode_tuple_header(oe_env, 2); if ((oe_error_code = oe_ei_encode_pid(oe_env,oe_env->_from_pid)) < 0) return oe_error_code; if ((oe_error_code = oe_ei_encode_ref(oe_env,&oe_env->_unique)) < 0) return oe_error_code; oe_ei_encode_atom(oe_env, "produce"); return 0; } /* * Decodes the return value for "rmod_random_produce" */ int rmod_random_produce__client_dec(rmod_random oe_obj, CORBA_double* oe_result, CORBA_Environment *oe_env) { int oe_error_code = 0; /* Decode result value: CORBA_double* oe_result */ if ((oe_error_code = ei_decode_double(oe_env->_inbuf, &oe_env->_iin, oe_result)) < 0) return oe_error_code; return 0; } /* * Object interface function "rmod_random_init" */ void rmod_random_init(rmod_random oe_obj, CORBA_long seed1, CORBA_long seed2, CORBA_long seed3, CORBA_Environment *oe_env) { /* Initiating exception indicator */ oe_env->_major = CORBA_NO_EXCEPTION; /* Creating call message */ if (rmod_random_init__client_enc(oe_obj, seed1, seed2, seed3, oe_env) < 0) { if (oe_env->_major == CORBA_NO_EXCEPTION) CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, MARSHAL, "Cannot encode message"); } /* Sending call request */ if (oe_env->_major == CORBA_NO_EXCEPTION) { if (strlen(oe_env->_regname) == 0) { if (ei_send_encoded(oe_env->_fd, oe_env->_to_pid, oe_env->_outbuf, oe_env->_iout) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE, "Cannot connect to server"); } } else if (ei_send_reg_encoded(oe_env->_fd, oe_env->_from_pid, oe_env->_regname, oe_env->_outbuf, oe_env->_iout) < 0) { CORBA_exc_set(oe_env, CORBA_SYSTEM_EXCEPTION, NO_RESPONSE, "Cannot connect to server"); } } } /* * Encodes the function call for "rmod_random_init" */ int rmod_random_init__client_enc(rmod_random oe_obj, CORBA_long seed1, CORBA_long seed2, CORBA_long seed3, CORBA_Environment *oe_env) { int oe_error_code = 0; oe_env->_iout = 0; oe_ei_encode_version(oe_env); oe_ei_encode_tuple_header(oe_env, 2); oe_ei_encode_atom(oe_env, "$gen_cast"); oe_ei_encode_tuple_header(oe_env, 4); oe_ei_encode_atom(oe_env, "init"); /* Encode parameter: CORBA_long seed1 */ if ((oe_error_code = oe_ei_encode_long(oe_env, seed1)) < 0) return oe_error_code; /* Encode parameter: CORBA_long seed2 */ if ((oe_error_code = oe_ei_encode_long(oe_env, seed2)) < 0) return oe_error_code; /* Encode parameter: CORBA_long seed3 */ if ((oe_error_code = oe_ei_encode_long(oe_env, seed3)) < 0) return oe_error_code; return 0; } /* * Generic function, used to return received message information. * Not used by oneways. Allways generated. */ int rmod_random__receive_info(rmod_random oe_obj, CORBA_Environment *oe_env) { int oe_error_code = 0; int oe_rec_version = 0; erlang_ref oe_unq; oe_env->_iin = 0; oe_env->_received = 0; if ((oe_error_code = ei_decode_version(oe_env->_inbuf, &oe_env->_iin, &oe_rec_version)) < 0) return oe_error_code; if ((oe_error_code = ei_decode_tuple_header(oe_env->_inbuf, &oe_env->_iin, &oe_env->_received)) < 0) return oe_error_code; if ((oe_error_code = ei_decode_ref(oe_env->_inbuf, &oe_env->_iin, &oe_unq)) < 0) return oe_error_code; /* Checking message reference*/ if(strcmp(oe_env->_unique.node,oe_unq.node) != 0) return -1; if(oe_env->_unique.id != oe_unq.id) return -1; return 0; }
Compiling the code:
ReadMe
file att the ic-3.2/examples/c-client
directory
![]() |
Due to changes to allow buffer expansion, a new receiving function some changes in CORBA_Environment initialization are applied. The example in the ic-3.2/examples/c-client directory demonstrates these changes. |
Running the example:
ReadMe
file att the ic-3.2/examples/c-client
directory