Manually Call a C++ Object's Initializer in C

227 views Asked by At

I am working on a small application that was written in C++ and would like to use on my platform. Unfortunately, our cross-compile toolchain only (reliably) provides a C compiler. I looked at the application, and it is fairly simple and only uses C++-specific idioms in a few places, so I thought I'd just convert it to C code by hand.

I bumped across one line that I'm not sure how to handle. The code is using Termios to open a new port to talk to a TTY stream, and initializes the Termios struct using the new keyword.

termios *settings = new termios();

As I understand it, the new keyword, in addition to allocating the appropriate memory, calls the object's initializer. In C, after I allocate memory with malloc, can I manually call the initializer? Do I need to?

I have a feeling that I'm misunderstanding something obvious / fundamental or that I'm looking at this all wrong. I'm not very accustomed to C++ code.

edit: I seem to have caused some confusion. The line of code above is creating a new termios struct as defined in termios.h, part of the standard libraries on most implementations of C.

4

There are 4 answers

4
Casey On BEST ANSWER

The line

termios *settings = new termios();

allocates memory for a termios object and value-initializes it. Since termios is a POD, the equivalent C would be

struct termios* settings = calloc(1, sizeof(*settings));

or

struct termios* settings = malloc(sizeof(*settings));
memset(settings, 0, sizeof(*settings));

and of course the equivalent of delete settings would be free(settings).

1
Basile Starynkevitch On

Notice that termios is the name of a struct related to termios(3) function, so better not use that termios name in a Linux or POSIX program in C (i.e. avoid naming your types with usual types provided by system libraries).

BTW you should consider using some existing terminal IO library like ncurses or readline

At last, if you insist in having your own termios structure or class (which is practically a very bad idea, choose some other name) managed by your C++ library to be called by C, you should wrap its allocator+constructor & destructor+deallocator like this.

extern "C" struct termios* make_my_termios () {
   struct termios* ts = new termios;
   return ts;
}

extern "C" void destroy_my_termios(struct termios* ts) {
   delete ts;
}

And if you just use the genuine struct termios* (from termios(3)) in your C++ library, just keep it as it is...

0
AudioBubble On

I'd suggest creating a function

termios *new_termios()

that would combine malloc with constructor code. After that, do not use malloc to allocate termios.

0
101010 On

"In C, after I allocate memory with malloc, can I manually call the initializer?

Unfortunately, you can't.

Do I need to?"

It really depends on the definition of termios objects. Basically, what malloc does is simply allocate a chunk of memory. That is, it doesn't do any initializations and inner memory allocations like a constructor does.

What I do in these situations:

I create C wrapper functions for my C++ objects with the help of opaque pointers. For example in order to call the constructor of a C++ object I would create a C++ wrapper for C in a .cpp file:

void* create_termios() { return new termios(); }
void  destroy_termios(void *obj) { delete obj; }
// other wrapper functions for termios

And then I would interface these functions in C with a .h file:

extern "C" {
    void* create_termios();
    void  destroy_termios(void *obj);
    // declare any other necessary wrappers
}