Makefile Mix for C and C++

Hi everyone,
I'm new in this forum. I hope you could help me with this code.
I'm trying to include in an ANSI C project, some (OpenCV) libraries made in C++.
When I included those libraries, the compiler threw the following error:

ardrone_testing_tool.c: (.text+0x1212) : undefined reference to `cvSURFParams'
ardrone_testing_tool.c: (.text+0x126f) : undefined reference to `cvExtractSURF'

Basically people told me to change the compiler to the g++ (if anyone think about a better solution, please tell me. However, I think I'll have to edit the Makefile of the project...). The main Makefile of the project uses some standard variables like MAKE, which calls recursively another makefile, in the folder VP_SDK/Build.

In that folder, the other makefile has some sections which calls again another makefiles to configure variables and so on. Finally it calls generic.makefile which sets the compiler and does the compilation.
The point is that now, when I changed the word gcc by g++ the compilation didn't work (the original version which had worked with the gcc).
The error that it gives is the following:

../../VLIB/video_codec.c: In function �int video_codec_open_private(video_controller_t*, codec_type_t, int32_t)':
../../VLIB/video_codec.c:75: error: invalid conversion from �void*' to �video_macroblock_t*'
../../VLIB/video_codec.c: In function �int video_codec_type_select(video_controller_t*, video_stream_t*)':
../../VLIB/video_codec.c:190: error: invalid conversion from �uint32_t' to �codec_type_t'
../../VLIB/video_codec.c:190: error: initializing argument 2 of �int video_codec_open_private(video_controller_t*, codec_type_t, int32_t)'
../../VLIB/video_codec.c: In function �int video_encode_picture(video_controller_t*, const vp_api_picture_t*, int32_t*)':
../../VLIB/video_codec.c:198: error: invalid conversion from �int' to �PixelFormat'
../../VLIB/video_codec.c: In function �int video_decode_picture(video_controller_t*, vp_api_picture_t*, video_stream_t*, int32_t*)':
../../VLIB/video_codec.c:237: error: invalid conversion from �int' to �PixelFormat'

That is, an error previously hadn't detected by the gcc.
So, I think maybe I should differentiate in the code the treatment of .cpp files and the other files.

Below in the post you will see some parts of the code. In the macro INTERNAL_SOURCE_EXTENSIONS, there are defined the extensions .c .S .s .cpp. You can see also that there are some other macros that depend on that... For example INTERNAL_BINARIES_COMMON_TARGET_OFILES, which after is used to do different things (and compilation of course).
Anyway, I'm thinking of doing something like duplicating some macros, to do the compilation in two parts (on one side .c .S .s and on the other .cpp).
I don't know much about makefiles, so I would like to know what do you think about that. Is that convinient to do? There is another better or easier way to make it work?
Here I show you some lines of the file generic.makefile, but I could put all the code if you think is necessary.
I will be really appreciated if you give me some help. May be for some of you is not quite difficult to see the changes that has to be made in the complete version of the code.

INTERNAL_SOURCE_EXTENSIONS= .c .S .s .cpp

INTERNAL_MKDIR=mkdir -p
INTERNAL_ECHO=echo

# (in) GENERIC_COMMAND_PREFIX
INTERNAL_CC:=$(GENERIC_COMMAND_PREFIX)gcc
INTERNAL_AR:=$(GENERIC_COMMAND_PREFIX)ar
INTERNAL_OBJCOPY:=$(GENERIC_COMMAND_PREFIX)objcopy
INTERNAL_STRIP:=$(GENERIC_COMMAND_PREFIX)strip

# (in) GENERIC_CFLAGS    # (in) GENERIC_LDFLAGS
# (in) GENERIC_ARFLAGS     # (in) GENERIC_INCLUDES
# (in) GENERIC_ADD_OFILES : for linking with     # (in) GENERIC_LIBRARY_SOURCE_DIR
# (in) GENERIC_LIBRARY_SOURCE_FILES     # (in) GENERIC_LIBRARY_TARGET_DIR : for .o files
INTERNAL_LIBRARY_SOURCE_FILES:=$(patsubst %,$(GENERIC_LIBRARY_SOURCE_DIR)/%,$(GENERIC_LIBRARY_SOURCE_FILES))
INTERNAL_LIBRARY_TARGET_OFILES:=$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),\
	$(patsubst $(GENERIC_LIBRARY_SOURCE_DIR)/%$(ext),$(GENERIC_LIBRARY_TARGET_DIR)/%.o,$(filter %$(ext),$(INTERNAL_LIBRARY_SOURCE_FILES))))

# (in) GENERIC_BINARIES_SOURCE_DIR   # (in) GENERIC_BINARIES_COMMON_SOURCE_FILES   # (in) GENERIC_BINARIES_SOURCE_ENTRYPOINTS    # (in) GENERIC_BINARIES_TARGET_DIR : for .o files

INTERNAL_BINARIES_COMMON_SOURCE_FILES:=$(patsubst %,$(GENERIC_BINARIES_SOURCE_DIR)/%,$(GENERIC_BINARIES_COMMON_SOURCE_FILES))
INTERNAL_BINARIES_COMMON_TARGET_OFILES:=$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),\
	$(patsubst $(GENERIC_BINARIES_SOURCE_DIR)/%$(ext),$(GENERIC_BINARIES_TARGET_DIR)/%.o,$(filter %$(ext),$(INTERNAL_BINARIES_COMMON_SOURCE_FILES))))
INTERNAL_BINARIES_TARGET_OENTRYPOINTS:=$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),\
	$(patsubst %$(ext),$(GENERIC_BINARIES_TARGET_DIR)/%.o,$(filter %$(ext),$(GENERIC_BINARIES_SOURCE_ENTRYPOINTS))))

===================================

ifeq ($(USE_DLL),yes)
	$(GENERIC_COMMAND_PREFIX)dlltool -e $(GENERIC_TARGET_BINARIES_DIR)/$(DLL_ID)_exports.o --export-all-symbols -l $(@:.dll=.lib) $(INTERNAL_BINARIES_COMMON_TARGET_OFILES)
	$(INTERNAL_CC) --shared -o $@ $(INTERNAL_BINARIES_COMMON_TARGET_OFILES) $(GENERIC_TARGET_BINARIES_DIR)/$(DLL_ID)_exports.o $(GENERIC_ADD_OFILES) $(GENERIC_LIB_PATHS) $(GENERIC_LIBS) $(GENERIC_LDFLAGS) $(LDFLAGS_$(subst /,_,$*))
	$(RM) $(GENERIC_TARGET_BINARIES_DIR)/$(DLL_ID)_exports.o
  else
	$(INTERNAL_CC) -o $@ $(GENERIC_BINARIES_TARGET_DIR)/$*.o $(INTERNAL_BINARIES_COMMON_TARGET_OFILES) $(GENERIC_ADD_OFILES) $(GENERIC_LIB_PATHS) $(GENERIC_LIBS) $(GENERIC_LDFLAGS) $(LDFLAGS_$(subst /,_,$*))
  endif

===================================

# Build rules for each extension
$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),$(eval $(call BUILD_OFILE_TEMPLATE,LIBRARY,$(ext))))
$(foreach ext,$(INTERNAL_SOURCE_EXTENSIONS),$(eval $(call BUILD_OFILE_TEMPLATE,BINARIES,$(ext))))

ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),check)
  -include $(INTERNAL_LIBRARY_DEPFILES) $(INTERNAL_BINARIES_DEPFILES)
endif
endif

Thank You all for any comments that you could give me.

Best Regards,

Hern�n.

When you want to reference C++ variables in C, you must declare them in C using the wrapper "extern C++ { . . . }", even by way of include file #include lines, and vice-versa with "extern C { . . . }". C++ names are mangled to indicate the type returned and, if method/subroutine/function, the number and types of arguments, for stricter type checking. The original C++ compilers were just preprocessors for the C compiler. If you look at some object code (executables and libraries) using nm, you will see the mangled names of C++ identifiers.

Your make rules need to point to different compiler commands and arguments, using different variables, e.g., not swapping CC from gcc to g++. Sometimes it simplifies things if you use a different directory, or ensure even include files have different suffixes for c++. Try not to make whole new compile lines for every file, but just modify a variable referenced in the common line for moving from one extension to the next. If object file order on linking line is getting to be a pain, remember that code is library files, static or dynamic, is not order sensitive. Even main() can be in a library if all the code in the library serves that main. One class per include file and one subroutine/method/class per non-include file, all compiled -c and non-main() .o put in libraries, is a good practice.

Thank you DGPickett for your answer.
I've been looking for the use of extern in ANSI C, and I tried several ways to code it:

extern "C++" {
      #include <opencv2/features2d/features2d.hpp>
}

But it didn't work (the compiler threw errors because of the quotation marks or the braces... I changed them by parenthesis and simple quotation marks, but It didn't work. After I found a post (*) that say that C does not define linkage to any other language (but C++ does).
So I tried with extern "C" in the c++ library, but when I compiled it threw the same compilation error...

ardrone_testing_tool.c: (.text+0x1212) : undefined reference to `cvSURFParams'
ardrone_testing_tool.c: (.text+0x126f) : undefined reference to `cvExtractSURF'

In that link, they say also that I could try with the compiler g++ (I should fix the errors I put in the last post).
What do you think about that?

Concerning the compiler, you mean to take out '.cpp' in INTERNAL_SOURCE_EXTENSIONS, and after put the .hpp file in a separated folder and call the g++ just for that folder and generate the .o ?
How can I put all the .o files all together ?

Is it OK what I'm saying? Sorry if I'm saying something that is wrong, I started just some days ago with the GNU makefile.

Thanks a lot.

(*) The forum does not allow to put links before 5 posts. Write on google "linking a C++ library to a C program" bytes

What are you actually trying to do? Are you attempting to use C++ classes inside C(C doesn't have classes), or just use some external functions from C++ code?

Are you actually compiling the library, too? Perhaps you could modify it to export C symbols. That'd be simpler and more portable than trying to import C++ ones. If it's exporting functions rather than classes, it really should export them with C linkage anyway, since that'd make the library equally usable in C++ and C.

extern "C" - C++ Forum

On all C++ compilers, extern "C" {} turns off mangling so C++ can call C. You use it in the C++ files only, to call C functions that have no C++ versions, i.e., when necessary.

Newer C compilers can mangle names and call C++ functions, if you declare them with extern "C++" in the C files only.

cc -c compiles something.c into (usually) something.o, an unlinked object file. If you want to link to static library somelib.a or prepare it to run-time link to dynamic library somelib.so, a second pass of cc -o something, or an internal second pass if no -c, links (actually using ld) the .o and library stuff together to an exec() friendly executable object file. Static libraries are archves from ar of *.o files, and ld copies the relevant parts of them into the statically linked executable. Dynamic libraries can be made for static ones, perhaps internally linking modules that call each other, and of course geting a new suffix and magic. Dynamic executable files just have stubs to allow a call to ld() at run time to find .so libraries in the original or $LD_LIBRARY_PATH directories, mmap() them into the memory space of the process, and set pointers to the mapped parts. All running copies of 'something' use the same .so file mapped into the same RAM pages, except for initialized modifiable variables, which are often just initialization constants and a spec for variable space, so non-variable parts can be mapped into read-only pages. Statically linked copies of something *might all use separate RAM copies of the code, if exec() does not use mmap(), and they roll out on separate parts of swap. Dynamic is especially wise when many programs use the same calls, so they use the same RAM & cache, and not so much swap. For instance, most C programs use libc, so it is linked by default. In dynamic mode, all C programs use the same libc.so mapped in the same RAM pages. If your dynamically linked executable goes to machines with a too different libc.so, they fail. Static linking means that never happens. Dynamic linking is for real men! :smiley: You can ensure the right libraries are found with $LD_LIBRARY_PATH, just the same way you might control where 'cc' is found using $PATH.

BTW, set-uid and set-gid executables unset the $LD_LIBRARY_PATH so you need to compile them without moving the .so from run time, and often with a cc option like -R to burn in fixed library paths at compile time. This is why it is so hard to write a set-uid script -- interpreter cannot link. You have to write your own fixed path interpreter wrapper!