For reasons beyond my control, I need to return const char*
from a function, but I don't know what the char
s need to be at compile time. My solution is something like the following:
const char* __str__() {
static std::string String;
String = [some fancy stuff];
return String.c_str();
}
The static
prevents the string's destruction on exiting the function, but it also means that the memory sticks around until my program exits (right?). Because the returned string can occasionally be huge (GBs), this can be a real problem.
I usually avoid pointers at all costs and only ever use static
for class members, so I'm not 100% sure what I'm doing. Is this guaranteed to work? Is there a better way?
[The context of this question is printing a complicated object in python, using the __str__
method. I define the method in my c++ code, which is then wrapped by SWIG. The SWIG example shows the use of static
, but it's not clear to me that that's the only way. I am open to suggestions.]
static
presents additional troubles besides the allocation scope:
Any reason not to return the value and let the caller free it?:
const char* __str__() {
char *s = malloc(2 * 1024 * 1024 * 1024); // 2 GB
[some fancy stuff with s];
return s;
}
...
const char *magic = __str__();
[do something with magic]
free (magic); magic = NULL; // all done
As @Prætorian said, SWIG can return std::string to Python. Here's an example from the SWIG example I think you are looking at. Also shown is a way to avoid using a reserved name in C++:
%module x
%{
#include "x.h"
%}
%include <windows.i>
%include <std_string.i>
%rename(__str__) display;
%include "x.h"
#include <sstream>
#include <string>
class Vector
{
public:
double x,y,z;
Vector(double a,double b,double c):x(a),y(b),z(c) {}
~Vector() {}
#ifdef SWIG
%extend {
std::string display()
{
std::ostringstream temp;
temp << '[' << $self->x << ',' << $self->y << ',' << $self->z << ']';
return temp.str();
}
}
#endif
};
Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import x
>>> v = x.Vector(1.0,2.5,3.0)
>>> print v
[1,2.5,3]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With