Question

I am using an external C++ lib that does some HTTPS communication and provides the XML server response. On serverside the response is encoded via ISO-8859-15 and I get a std::string that represents that response out of the API. When I print it out / write it to a file it looks proper.

The std::string and an int error code have to be passed to my external caller. So I return both values inside a struct:

extern "C" {
  struct FoobarResponse {
    const char* responseText;
    int returnCode;
  };
}

Unfortunately I have to convert the std::string response into a const char* C-style string representation with help of std::c_str() before. Reason: My caller is a Ruby script making use of Ruby FFI to communicate with my C++ lib, and interlanguage type conversion here is Ruby::string -> C::const char*.

Interesting here: If I std::cout the converted string after I put it into the struct, it is still ok.

The problem: When handling the server response on Ruby side, it is broken. Instead of the original answer like:

<?xml version="1.0" encoding="ISO-8859-15"?>
<Foobar xmlns="http://www.foobar.com/2012/XMLSchema">
  ...
</Foobar>

I receive a string obviously containing non printable characters which is always broken at the beginning and at the end.

?O[
l version="1.0" encoding="ISO-8859-15"?>
<Foobar xmlns="http://www.foobar.com/2012/XMLSchema">
</Fo??

In fact the string contains linebreaks, carriage returns and tabs at least, maybe more.

I tried to :force_encoding the string on Ruby side as ASCII-8BIT, ISO-8859-15 and UTF-8, no change. I tried to base64 encode on C++ side before putting the string into the struct and base64 decode on Ruby side using this code, no change.

I had countless attepts to convert the string using Iconv as well, no change.

I also tried to remove non printable characters from the string before putting it into the struct, but I failed on that.

I have no idea what is going on here and running out of options. Can someone point me into the right direction?

Regards Felix

Was it helpful?

Solution

The value returned by c_str() is destroyed as soon as the std::string goes out of scope. If you intend to pass this value to your script you should allocate memory and copy the string into your newly allocated space. See this example: http://www.cplusplus.com/reference/string/string/c_str/

You should also ensure the ruby script will correctly release memory.

I think this is what is explained there: https://github.com/ffi/ffi/wiki/Examples.

Example with a struct passed to Ruby from C: https://github.com/ffi/ffi/wiki/Examples#-structs

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top