Wrapper around C lib, problem with c_str and const

F

Fred Paris

Hi

I'm writing a class to act as a wrapper around a C library.

This C library exposes functions like:

SetSomeInfo( char *pTheInfo );

In my wrapper class, the info in question is in a STL string.

std::string m_TheInfo;

So inside the wrapper class I would like to call:

SetSomeInfo( m_TheInfo.c_str() );

But, problem:

c_str returns a const char *, and SetSomeInfo accepts a char * (not
const), so it doesn't compile. Maybe SetSomeInfo is poorly written,
because it should have const in its signature, but it's not mine and
I have no control over it.

So my (rather ugly) workaround right now is:

char *p = (char *)(DWORD) m_TheInfo.c_str() ; //get rid of const

but surely there has to be a more standard way ?

Thanks
 
S

Shezan Baig

Fred said:
[snip]

char *p = (char *)(DWORD) m_TheInfo.c_str() ; //get rid of const

but surely there has to be a more standard way ?


Sure:

char *p = const_cast<char*>(m_TheInfo.c_str());

But make sure that the function *really* doesn't modify 'p', otherwise
you might run into undefined behaviour.

If you want to be absolutely safe and more elegant (avoiding the
const_cast and possible undefined behaviour), you can do something
like:

enum { BUF_SIZE = 1024 };

char p[BUF_SIZE];
strncpy(p, m_TheInfo.c_str(), BUF_SIZE);
p[BUF_SIZE-1] = 0;

Hope this helps,
-shez-
 
B

benben

Fred Paris said:
Hi

I'm writing a class to act as a wrapper around a C library.

This C library exposes functions like:

SetSomeInfo( char *pTheInfo );

In my wrapper class, the info in question is in a STL string.

std::string m_TheInfo;

So inside the wrapper class I would like to call:

SetSomeInfo( m_TheInfo.c_str() );

The following should get you through compilation...but really ask yourself
if that is really what you want (notice the low level operations and
explicit exception handling which are rather ugly):

char* buff = new char[m_TheInfo.length() + 1];
std::copy(buff, m_TheInfo.begin(), m_TheInfo.end());
buff[m_TheInfo.length()] = '\0';
try
{
SetSomeInfo(buff);
}
catch (...)
{
delete[] buff;
throw;
}
delete[] buff;

But, problem:

c_str returns a const char *, and SetSomeInfo accepts a char * (not
const), so it doesn't compile. Maybe SetSomeInfo is poorly written,
because it should have const in its signature, but it's not mine and
I have no control over it.

So my (rather ugly) workaround right now is:

char *p = (char *)(DWORD) m_TheInfo.c_str() ; //get rid of const

Don't do this. You may corrupt the string object and your program may not
recover from such brutal operation. NOT COOL!! std::string::c_str() returns
a const char* for a reason, most likely to set up protection against misuse.
 
J

John Carson

Fred Paris said:
Hi

I'm writing a class to act as a wrapper around a C library.

This C library exposes functions like:

SetSomeInfo( char *pTheInfo );

In my wrapper class, the info in question is in a STL string.

std::string m_TheInfo;

So inside the wrapper class I would like to call:

SetSomeInfo( m_TheInfo.c_str() );

But, problem:

c_str returns a const char *, and SetSomeInfo accepts a char * (not
const), so it doesn't compile. Maybe SetSomeInfo is poorly written,
because it should have const in its signature, but it's not mine and
I have no control over it.

So my (rather ugly) workaround right now is:

char *p = (char *)(DWORD) m_TheInfo.c_str() ; //get rid of const

but surely there has to be a more standard way ?

Thanks


SetSomeInfo(const_cast<char*>( m_TheInfo.c_str() ));
 
S

Shezan Baig

benben said:
The following should get you through compilation...but really ask yourself
if that is really what you want (notice the low level operations and
explicit exception handling which are rather ugly):


Or, you could just use a vector<char>:

vector<char> buff(m_TheInfo.length() + 1);
....

This gets rid of all the exception handling ugliness. Note however
that vector<char> will likely allocate, and if you know that the string
is never going to be more than a certain length, its probably better if
you just use a local buffer. You might want to throw an exception if
it exceeds this "maximum" length.

Many people often underestimate the cost of allocation/deallocation,
especially in multi-threaded environments where memory contention
becomes a much bigger issue than in single-threaded environments.

Hope this helps,
-shez-
 
B

benben

Shezan Baig said:
Or, you could just use a vector<char>:

vector<char> buff(m_TheInfo.length() + 1);

Eureka! Sure, I just forgot that a vector guarantees continuous memory block
haha.
...

This gets rid of all the exception handling ugliness. Note however
that vector<char> will likely allocate, and if you know that the string
is never going to be more than a certain length, its probably better if
you just use a local buffer. You might want to throw an exception if
it exceeds this "maximum" length.

That is to say we need a better allocator.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top