[omniORB] strings parameters passing rules.

Clarke Brunt clarke.brunt at yeomannavigation.co.uk
Wed Oct 8 13:40:11 BST 2003


I'll have a go at an answer, but if in doubt I would normally read the CORBA
C++ language mapping spec, and/or step into the Omni source code in the
debugger to see what the various _var, _out, _member types actually do. It
will be a miracle if I avoid making some mistake in this reply!

>With the idl file:
>
>struct Vls {
>  long l_mem;
>  string s_mem;
>};
>
>interface Foo {
>  Vls vls_op( in Vls vls_in, inout Vls vls_inout, out Vls vls_out ) ;
>};
>
>If i have a method:

>void my_func( const char *str_in, char *str_inout )

That second argument worries me a bit. This is just a C++ method, not a
CORBA method, and you are implying by naming this argument _inout that you
intend modifying something. But coded like this, all you could do would be
to overwrite the memory pointed at by str_inout. Your line (4) str_inout =
... doesn't acheive anything, as it can't pass the result back to the
caller.

You need to declare the argument as char*& (as CORBA would), or as char** if
you want to do it that way instead.

>{
>  Foo_var fv = ...; // Get reference
>
>  Vls in_val;
>  Vls inout_val;
>  Vls *out_val;
>  Vls *ret_val;

You would be better declaring the last two as Vls_var (without *), then they
will be freed automatically. If not, then you need 'free out_val;' and 'free
ret_val;'.

>  in_val.l_mem = 99;
>1)  in_val.s_mem = str_in;
>2)  in_val.s_mem = CORBA::string_dup( str_in );

I think that these are identical (but you would have to check). The reason
is that assigment to String_var (or a string member in this case) from a
const char* performs a duplicate anyway. I prefer to use line (2) as it
makes it clear what is happening. You don't want line (3) in either case, as
the destructor for Vls will free its members when it goes out of scope.

>  inout_val.l_mem = 99;
>  inout_val.s_mem = CORBA::string_dup( str_inout );

Change this line according to how you have declared the str_inout argument
above (i.e. OK for char *&, needs *str_inout if declared as char**).

>  ret_val = fv->vls_op( in_val, inout_val, out_val );

>3) CORBA::string_free( in_val.s_mem );

As I said above, you don't want this line. The structures will free it
themselves, so you would end up trying to free it twice.

>4) str_inout = inout_val.s_mem;

And what you really want here (if str_inout declared as char *&) is
str_inout = CORBA::string_dup(inout_val.s_mem)

>...
>
>If i put 2) then i have to put 3).

I claim that you don't have to put (3). Indeed you _must not_ put it.

>My questions are:
>
>The 1) is correct ? or always i have to do 2)

Either are OK. I prefer (2). Relying on automatic duplication of const char*
is to my mind dangerous, as if the 'const' somehow disappears, then you
might then find that 'ownership' of the char* has been taken over by the
_var (or member).

>And what about 4) ? Who have to free this resource ?

The caller of my_func needs to free it, as usual best done my using _var
types.

One way to call the new my_func (with char*& second argument) would be:

CORBA::String_var inout_val;
inout_val = CORBA::string_dup("Input value for inout string");

my_func("In string", inout_val);

printf("inout_val now contains %s\n", (const char*)inout_val);

...and the destructor for inout_val will automatically free the new
contents.

--
Clarke Brunt, Principal Software Engineer, Yeoman Navigation




More information about the omniORB-list mailing list