wally
wally

Reputation: 11032

Safe way to call a function with a void pointer parameter

I am calling a function documented as follows:

int BIO_write_filename(BIO *b, char *name)

with the following:

std::string filename{"myfile"};
if (BIO_write_filename(bio, filename.c_str()) <= 0) {
    throw std::runtime_error{"Could not prepare output file.\n"};
}

But I get the following error: cannot convert argument 4 from 'const char *' to 'void *'

I discovered that I'm actually dealing with a macro:

# define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, BIO_CLOSE|BIO_FP_WRITE,name)

So what I'm actually calling is:

long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg);

What is the best way to call this from C++?

So far I'm considering the following two options:


Option 1: c-style cast:

BIO_write_filename(bio, (void*)filename.c_str())

Option 2: C++ type cast:

const void* filename_ptr_c{(filename.c_str())};
void* filename_ptr{const_cast<void*>(filename_ptr_c)};
BIO_write_filename(bio, filename_ptr)

Upvotes: 2

Views: 220

Answers (2)

Jonathan Mee
Jonathan Mee

Reputation: 38959

In answer to your question. Use C++ style casts. They were added to C++ because C++ style casts to supersede C-Style casts. You can read more about the justification for C++ casts here: https://softwareengineering.stackexchange.com/questions/50442/c-style-casts-or-c-style-casts

As a bonus though, I'd suggest you eliminate the macro. As you have seen macros are a toxic element in C++. A vast improvement over either of your options would be:

if(BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_WRITE, data(filename)) <= 0L)

This does use C++17's: data so if you don't have access to that feel free to just use the const_cast<char*> and allow the cast to void* to occur implicitly.

Upvotes: 1

R Sahu
R Sahu

Reputation: 206717

My suggestion:

BIO_write_filename(bio, const_cast<char*>(filename.c_str()));

Upvotes: 1

Related Questions