[英]How to call a lib written in C++ from C?
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. 从demangling等的角度来看,我不认为这是一个大问题,但我无法弄清楚,我怎么能写一个小C程序从一个小小的C ++库调用一个函数。
I am on linux right now, trying with static binding. 我现在在linux上,尝试使用静态绑定。
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.
有趣的是,在SO上也没有这样的问题。
I do not even know IF this can work, far lesser HOW this has to be done. 我甚至不知道如果这可以工作,那么必须如何做得更少。
Typically, you need to force the C++ compiler to build the library with C linkage for the exported functions. 通常,您需要强制C ++编译器为导出的函数构建具有C链接的库。
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. 通常,链接器将对函数执行C ++名称修改,以便C链接器无法找到它们。
extern "C"
forces it not to do that. extern "C"
迫使它不这样做。 You need to wrap it in the #ifdef
, because extern "C"
isn't valid in C. 你需要将它包装在
#ifdef
,因为extern "C"
在C中无效。
UPDATE 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). 正如Charles Salvia在下面的评论中所说,你需要确保没有异常通过你的界面出来,因为C无法处理它们(至少不是与平台无关的方式)。
If the C++ library does not provide a C interface, then you can't. 如果C ++库没有提供C接口,那么你就不能。
If it does, use C interface. 如果是,请使用C接口。
If you are the author, use the extern "C"
feature. 如果您是作者,请使用
extern "C"
功能。 http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
Personally, I'd write a C++ file that exports functions that use C linkage. 就个人而言,我写了一个C ++文件,导出使用C链接的函数。 In other words, write a binding.
换句话说,写一个绑定。
It is a problem from the point of demangling. 从解码的角度来看这是一个问题。 Use extern C around the C++ you want to call from C.
在要从C调用的C ++周围使用extern C.
Mangling and de-mangling was never standardized in C++, since it was deemed too platform dependent. 在C ++中, Mangling和de-mangling从未标准化,因为它被认为太依赖于平台。 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.
结果是,虽然通过查看链接器输出可以找出C ++方法的方法名称,但是没有可移植的方法来查找C ++函数方法的“真实”可链接名称。
On Linux, you can get the mangled name of your C++ functions with the command 在Linux上,您可以使用该命令获取C ++函数的错位名称
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... 通过它的受损名称从C调用函数,但不要指望这个技巧是可移植的......
Edit : then you have to link using g++, or with gcc -lstdc++ 编辑 :然后你必须使用g ++或gcc -lstdc ++进行链接
You can write a C wrapper around any C++ library that has a C++ API. 您可以在任何具有C ++ API的C ++库周围编写C包装器。 The wrapper should be written in C++.
包装器应该用C ++编写。
You can even use your C++ classes. 您甚至可以使用C ++类。 You forwardly declare them as struct.
你将它们声明为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. 适用于所有C功能。 in the header only, put
只在标题中,放
#ifdef __cplusplus
extern "C" {
#endif
// all your functions
#ifdef __cplusplus
}
#endif
Typical wrapper looks like this: 典型的包装器看起来像这样:
---- class_a.hpp ---- ---- class_a.hpp ----
#include "class_a_wrapper"
class A {
public:
int foo(double p);
double bar(int x, int y);
}
---- class_a_wrapper.h ---- ---- 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 ---- ---- 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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.