Using Static C++ Library in C

I'm having problems linking a static C++ library in C.

I have already done it with shared library and dynamic linking using a wrapper library..

libCPP.a ⟵ C++ library (g++ -fpic shared )
libCPPWrapper.a ⟵ C Wrapper (g++ -fpic shared -lCPP)
main.exe ⟵ C Program (gcc -lCPPWrapper)

What's the compilation and linking setup with static C++ library and C?

Looking for at least a simple example. I'm using MinGW compiler.
Last edited on
To tell the c++ compiler that you want c functions you need extern"C". See:

https://en.cppreference.com/w/cpp/language/language_linkage

That avoids the name mangling.
You can call a C function (possibly from a library) from C++ code, but not the other way around! Also, if you call a C function from C++ code, extern "C" disables the name mangling that a C++ compiler normally does.

That is why you will often see header files like this to make it work with C and C++ compiler:
1
2
3
4
5
6
7
8
9
#ifdef __cplusplus
extern "C" {
#endif

int some_function_name(int param1, int param2);

#ifdef __cplusplus
}
#endif 


If you must call a C++ method/class from C code, then I think the only option is to write a "wrapper" function in C++ that performs the actual call to the C++ method/class. This "wrapper" must be a simple function in global namespace (no class or anything), so that it can be called from C code. I do not think that there is any difference here between calling the C++ method/class from a "static" or "shared" library (or no library at all).

As for the actual linking, a "static" library file (.a) is really just an archive containing a bunch of compiled object code files (.o). So, there is no such thing as a "C" or "C++" library. There just are a bunch object code files (.o), each of which may have been compiled from C or C++ code, or maybe even from other languages...
Last edited on
Thanks for the response guys..

@kigar64551

I already have a wrapper for it and got the shared library version working,

so I'm asking how to do it using static, as I would like a single executable rather than having extra DLL.

I do not think that there is any difference here between calling the C++ method/class from a "static" or "shared" library (or no library at all).


Ok, I also read somewhere that you have to link all objects/libs in C++ and not C linker, even if the main program is C for this to work as static.

Last edited on
I really do not think the "C wrapper around C++ class/method call" approach makes any difference between "shared" or "static" libraries; or whether the C++ class to be called is directly from your "main" project.

But I do think that if your link any object files (.o), either directly or from a (static) library, that were generated by the C++ compiler, then you also have to use the C++ linker. Or, more specifically, you have to use the C++ compiler "driver" (e.g. g++ instead of gcc), which will invoke the linker (e.g. ln) for you in the proper way.

That is because C++ code requires the C++ Standard Library and stuff to be linked!

Try like this:
1
2
3
gcc -c main.c -o main.o
g++ -c wrapper.cpp -o wrapper.o
g++ -static -o myprogram.exe main.o wrapper.o -lfoobar

(assuming the library is "libfoobar.a")

Note: You probably want to use the -static linker switch too, because otherwise your EXE file will still depend on the "shared" C++ Standard Library (e.g. libstdc++-6.dll) file, as well as other "runtime" DLL files.

You can always check for runtime dependencies with this tool:
https://github.com/lucasg/Dependencies
Last edited on
Thanks for the additional info. Yes, I have no problem with g++ as the linker, it's when the linker is using gcc.

Is there anyway I can merge a wrapper DLL and the c++ library DLL into one DLL and link to C linker? this is not static anymore or perhaps should be another topic/question.
"Merging" two existing (binary) DLL files into one DLL files is not possible with "standard" tools.

But, if you build the C++ DLL yourself, from the sources, then, when building that DLL file, you can link the "C wrapper" functions into the same DLL as the C++ classes/methods to be invoked.

Such DLL will, of course, need to be built with the C++ compiler/linker tools (e.g. g++), and it certainly will come out with runtime-dependencies on the C++ Standard Library (e.g. libstdc++-6.dll) and friends.

I think it then should be possible, for a "pure" C program (EXE file), to link against the "combined" C/C++ DLL file – provided that the C program exclusively calls the "C wrapper" functions exported from that DLL. And, I think, in this scenario, the "main" (pure C) program can be built using the C compiler/linker (e.g. gcc).

Note: Even though the "main" (pure C) program will not have a direct dependency on the C++ Standard Library, it still will have an indirect dependency on the C++ Standard Library, via the linked C/C++ DLL.
Last edited on
Yes, it's from the sources.
Last edited on
Then you can try something like this:

my_class.h:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _INC_MYCLASS
#define _INC_MYCLASS

class MyClass
{
public:
	int add(const int a, const int b);
private:
	const int magic = 42;
};

#endif //_INC_MYCLASS 

my_class.cpp:
1
2
3
4
5
6
#include "my_class.h"

int MyClass::add(const int a, const int b)
{
	return a + b + magic;
}

wrapper.h:
1
2
3
4
5
6
7
8
9
#ifdef __cplusplus
extern "C" {
#endif

int wrapper(const int a, const int b);

#ifdef __cplusplus
}
#endif 

wrapper.cpp:
1
2
3
4
5
6
7
8
9
10
11
#include "wrapper.h"
#include "my_class.h"

extern "C"
{
	int wrapper(const int a, const int b)
	{
		MyClass instance;
		return instance.add(a, b);
	}
}

main.c:
1
2
3
4
5
6
7
#include "wrapper.h"
#include <stdio.h>

int main()
{
	printf("%d\n\n", wrapper(7, 13));
}


Build command:
1
2
g++ -o library.dll my_class.cpp wrapper.cpp -shared -Wl,-out-implib,library.dll.a
gcc -o program.exe main.c library.dll.a


Result:
https://i.imgur.com/okorEFs.png
thanks, aside from the error/warning iso c++ forbids initialization of member of magic, it works for combining the wrapper source and class as 1 DLL.

Going back to the original question: So I did figure out that a C++ compiler can only link a Main C source to a C++ static library by wrapper and should be the same compiler and version.

Last edited on
Keep in mind that programs like gcc and g++ are so-called "drivers" that will invoke the actual compiler and/or linker in the background, as needed. They also take care of linking certain default libraries.

Now, if you link a program with gcc (rather than g++), it will only link the default libraries that are required for C code, not those additionally required for C++ code (such as the C++ Standard Library).

I think that is the reasons (or one of the reasons) why linking with gcc is going to fail, if you try to link any object files (and "static" libraries are really just a collection of object files) containing C++ code.
Last edited on
Topic archived. No new replies allowed.