可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
It seems to me like a no-brainer, but I cannot find any information against or for it.
From the point of view of demangling etc, I don't suppose this to be a big problem, but I can't figure out, how I can write a little tiny C program which calls a function from a little tiny C++ library.
I am on linux right now, trying with static binding.
This must be something many people are running into or many books cover, but I feel like a blind gump sitting in front of this problem. Interestingly, there is no such question on SO either.
I do not even know IF this can work, far lesser HOW this has to be done.
回答1:
Typically, you need to force the C++ compiler to build the library with C linkage for the exported functions.
You can do that by doing the following to your header:
#ifdef __cplusplus
extern "C" {
#endif
void func(void);
/* ... Other function defs go here ... */
#ifdef __cplusplus
}
#endif
Normally, the linker will do C++ name-mangling to the functions, so that the C linker won't be able to find them. extern "C"
forces it not to do that. You need to wrap it in the #ifdef
, because extern "C"
isn't valid in C.
UPDATE
As Charles Salvia says in a comment below, you need to ensure that no exceptions make their way out through your interface, because C has no way of handling them (at least not a platform-independent way).
回答2:
If the C++ library does not provide a C interface, then you can't.
If it does, use C interface.
If you are the author, use the extern "C"
feature. http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
回答3:
Personally, I'd write a C++ file that exports functions that use C linkage. In other words, write a binding.
回答4:
On Linux, you can get the mangled name of your C++ functions with the command
nm my-tiny-c++lib.a
Call the function from C by it's mangled name, but do not expect this trick to be portable...
Edit: then you have to link using g++, or with gcc -lstdc++
回答5:
It is a problem from the point of demangling. Use extern C around the C++ you want to call from C.
Mangling and de-mangling was never standardized in C++, since it was deemed too platform dependent. The result is, that while you could figure out the method name of a C++ method by looking at the linker output, there is no portable way of finding the "real" linkable name of a C++ method of function.
回答6:
You can write a C wrapper around any C++ library that has a C++ API. The wrapper should be written in C++.
You can even use your C++ classes. You forwardly declare them as struct. Some compilers will give a warning if you do this but you can probably either disable this warning or just ignore it.
You now create free-functions to create a pointer to such a struct (not an instance, as you don't see its full definition) and to dispose of such a pointer and all its methods by taking it as a parameter.
Note that if the class is in a namespace, you won't be able to do this so create your own struct that has just that member and use that "wrapper" instead.
For all your C functions. in the header only, put
#ifdef __cplusplus
extern "C" {
#endif
// all your functions
#ifdef __cplusplus
}
#endif
回答7:
Typical wrapper looks like this:
---- class_a.hpp ----
#include "class_a_wrapper"
class A {
public:
int foo(double p);
double bar(int x, int y);
}
---- class_a_wrapper.h ----
#ifdef __cplusplus
extern "C" {
#endif
struct wrap_A;
int wrap_A_foo(struct wrap_A *obj, double p);
double wrap_A_bar(struct wrap_A *obj, int x, int y);
#ifdef __cplusplus
}
#endif
---- class_a_wrapper.cpp ----
#include "class_a.hpp"
int wrap_A_foo(struct wrap_A *obj, double p) {
return (static_cast<A*>obj)->foo(p);
}
double wrap_A_bar(struct wrap_A *obj, int x, int y) {
return (static_cast<A*>obj)->bar(x, y);
}