How to call a lib written in C++ from C?

﹥>﹥吖頭↗ 提交于 2019-12-01 08:19:24

问题


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);
}


来源:https://stackoverflow.com/questions/4014851/how-to-call-a-lib-written-in-c-from-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!