[omniORB] Non-NULL terminated strings

Michael omniorb at bindone.de
Thu Apr 17 21:38:41 BST 2008


Hi,

I would suggest reading "Advances CORBA Programming with C++" and to get a copy of the
CORBA standard (for omniORB 2.6 seems to be the best choice to read), you can get it for
free on www.omg.org. Since the CORBA standard is basically pre-STL, none of the useful
containers/strings etc. of C++ are used (which sometimes makes it a pain to use). Your
best bet is to write some helper templates to ease using these constructs. CORBA in
general uses NULL-terminated strings everywhere (even for the non-C++ mappings like
Python). So sequence<char> or sequence<octet> are you best chances (even so personally I
would try to avoid the use of strings containnig 0, because it makes interoperability with
standard C APIs impossible).

Depending on your environment the sequence approach should be accepable performace-wise,
especially if you use strings internally and make only one call to do the conversion (so
you allocate the sequence and copy into it instead of growing it element by element).
Sequences of primitive types also allow you to provide a buffer allocated by yourself,
which might be intersting when doing calls - so you could avoid an extra copy on the
client side (read about the sequences for details). This will of course only for on IN
parameters.

Example:

Assume the IDL:
typedef sequence<char> StringData;
interface X
{
  void call(in StringData inString);
};

And client code using it:

StringData corba_string_in(std::string& s)
{
  return StringData(s.size(), s.size(), reinterpret_cast<CORBA::Char*>(&s[0]), false);
  // last parameter "false" means that StringData will not free the buffer on destruction
}

std::string s(...);
X_ptr x = ...;
x->call(corba_string_in(s));

This of course is neither nice nor necessarely very portable (+ I didn't test it), but by
encapsulating this hack into corba_string_in it should be very easy to change if
necessary. You might want to make this a little bit more sophisticated, so StringData
isn't modified by accident (which most likely will crash your application):

class InString
{
  std::auto_ptr<StringData> data_;

public:
  InString(std::string& s):
  data_(new StringData(s.size(), s.size(), reinterpret_cast<CORBA::Char*>(&s[0]), false))
  {}

  const Mine::StringData& in() const
  {
    return *data_.get();
  }
};

std::string s(...);
X_ptr x = ...;
x->call(InString(s).get());

For the server side you would of course need something like:

std::string to_string(const StringData& sd)
{
  return std::string(*(sd.get_buffer()), sd.length());
}

void X_impl::call(const StringData& inString)
{
  std::string s = to_string(inString);
}

Again, none of that is tested and I wouldn't consider it particulary good style.

Hope it helps anyway :)

cheers
michael

David wrote:
> Hi,
> 
> How would I represent a non-NULL terminated string in the best way? In the
> C++ codebase I'm working with, those kinds of strings are represented with a
> char * and a length field, put together in a struct. Unfortunately, omniidl
> seems to map the string type to a char *, and not a C++ string. This means
> that the IDL string datatype cannot be used for strings containing NULLs.
> The spontaneous workaround was to do this in IDL:
> 
> typedef sequence<char> StringData;
> 
> Will this be incredibly inefficient? Are there other collection-type
> datatypes in IDL, or is sequence the only one? Reason I'm asking is because
> I think it's quite a hassle to use. A growable list would be a lot easier to
> work with. Just to re-iterate, here's my original question: how do you guys
> handle this scenario? Any help is appreciated.
> 
> /David
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> omniORB-list mailing list
> omniORB-list at omniorb-support.com
> http://www.omniorb-support.com/mailman/listinfo/omniorb-list




More information about the omniORB-list mailing list