toozie21
toozie21

Reputation: 341

How do I combine a standalone c application into a c++ one?

I was working on a C++ app (call it recorder.cpp) that includes some C++ libraries from elsewhere (which have to use c++14, so I am stuck on that front). Currently my app is working, but it is just doing configuration based off of the external libraries and command line arguments.

There is a separate C app (call it receiver.c) that works independently that I basically want to combine with recorder. I think the easy way would be to copy and paste all of receiver into recorder, but that seems a bit redundant (not to mention if I make mods to receiver in the future, I will need to then make the same changes in recorder). So I was trying to figure out if there is a way to link them so that I can call receiver from the recorder app. I know that I can't just call receiver's main(), but I wasn't sure if there was a way to build receiver so that it acts more like a library yet still can be built as its standalone app.

Upvotes: 1

Views: 208

Answers (2)

Toby Speight
Toby Speight

Reputation: 30961

Just compile the object files recorder.o and receiver.o in the usual way. Make sure they don't both have a main() function: either #ifdef it out conditionally, or (better) compile it in its own object file for each program (e.g. recorder_main.cpp and receiver_main.c).

With this latter approach, the Makefile is quite simple, as we can let Make use its built-in rules to make the object files correctly. All we have to do is tell it how to link:

receiver: receiver_main.o receiver.o
        $(LINK.o) $^ $(LDLIBS) -o $@

recorder: recorder_main.o recorder.o receiver.o
        $(LINK.cc) $^ $(LDLIBS) -o $@

Notice that we need to link recorder with the C++ linker (that understands name mangling) rather than the C linker.

If you want separate source directories, that's easily managed using a VPATH in the Makefile.

Upvotes: 0

ryyker
ryyker

Reputation: 23236

"...I was trying to figure out if there is a way to link them so that I can call receiver from the recorder app."

Yes - But the simpler, more direct way is to copy the reciever.c code (minus its main() function) in with the C++ code. This would require that there is no syntax in the C code that would violate C++ rules. (eg. casting the return of malloc() for example is required in C++, but is not recommended in C.) But because most C syntax is completely C++ compatible, there should be little or no modifications necessary. Now all your code is together, and can be simply compiled as C++.

The linking approach however, would require compiling all of the functions of your stand-alone program (again, leaving out the main() function into a library. eg a DLL or shared library. That library can be linked using extern "C" { ... } within theC++ header file to surround the C function prototypes that are defined in the C library file. Those functions in the surround will be compiled with C linkage rather than C++. A brief example:

    // C++ code
    extern "C" void f(int); // one way
    extern "C" {    // another way
        int g(double);
        double h();
    };
    void code(int i, double d)
    {
        f(i);
        int ii = g(d);
        double dd = h();
        // ...
    }  

Reproduced from here...

Note, included in link is this statement: "...In addition, you’ll need to read the rest of this section to find out how to make your C functions callable by C++ and/or your C++ functions callable by C."

EDIT to add information from comments:
Regarding creating a library. The library could then be used by both programs and not maintained in two places. This would complicate versioning and there could be future issues if the 2 programs diverge in the future. Also note that using a static rather than shared library is also possible. These approaches have different versioning implications as future changes happen. (from @Avi Berger)

...Or, if your intent is to have a common *.c file so changes made for one app are easily included in the other, you don't make a library but simply link in the .o file. (from @Goswin von Brederlow)

Upvotes: 1

Related Questions