Reputation: 341
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
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
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 the
C++ 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();
// ...
}
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