在我看来,这似乎很简单,但我找不到任何反对或支持它的信息。
从拆解等的角度来看,我认为这不是一个大问题,但我不知道如何编写一个小小的 C 程序,它从一个小小的 C++ 库中调用一个函数。
我现在在 linux 上,尝试使用静态绑定。
这一定是很多人都遇到过的事情,或者很多书都涵盖了,但我觉得在这个问题面前就像一个盲人。有趣的是,在 SO 上也没有这样的问题。
我什至不知道这是否可行,更不用说如何完成了。
在我看来,这似乎很简单,但我找不到任何反对或支持它的信息。
从拆解等的角度来看,我认为这不是一个大问题,但我不知道如何编写一个小小的 C 程序,它从一个小小的 C++ 库中调用一个函数。
我现在在 linux 上,尝试使用静态绑定。
这一定是很多人都遇到过的事情,或者很多书都涵盖了,但我觉得在这个问题面前就像一个盲人。有趣的是,在 SO 上也没有这样的问题。
我什至不知道这是否可行,更不用说如何完成了。
通常,您需要强制 C++ 编译器为导出的函数构建带有 C 链接的库。
您可以通过对标题执行以下操作来做到这一点:
#ifdef __cplusplus
extern "C" {
#endif
void func(void);
/* ... Other function defs go here ... */
#ifdef __cplusplus
}
#endif
通常,链接器会对函数进行 C++ 名称修改,因此 C 链接器将无法找到它们。 extern "C"
强迫它不要那样做。您需要将其包装在#ifdef
, 因为extern "C"
在 C 中无效。
更新
正如 Charles Salvia 在下面的评论中所说,您需要确保没有异常通过您的界面,因为 C 无法处理它们(至少不是独立于平台的方式)。
如果 C++ 库不提供 C 接口,那么您不能。
如果是这样,请使用 C 接口。
如果您是作者,请使用该extern "C"
功能。http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
就个人而言,我会编写一个导出使用 C 链接的函数的 C++ 文件。换句话说,写一个绑定。
从拆解的角度来看,这是一个问题。在要从 C 调用的 C++ 周围使用extern C。
在 C++ 中,重整和反重整从未标准化,因为它被认为过于依赖平台。结果是,虽然您可以通过查看链接器输出找出 C++ 方法的方法名称,但没有可移植的方法来找到 C++ 函数方法的“真实”可链接名称。
在 Linux 上,您可以使用以下命令获取 C++ 函数的错位名称
nm my-tiny-c++lib.a
从 C 中调用函数时,它的名字是乱七八糟的,但不要指望这个技巧是可移植的......
编辑:那么您必须使用 g++ 或 gcc -lstdc++ 进行链接
您可以围绕任何具有 C++ API 的 C++ 库编写 C 包装器。包装器应该用 C++ 编写。
您甚至可以使用您的 C++ 类。您向前将它们声明为结构。如果您这样做,一些编译器会发出警告,但您可以禁用此警告或忽略它。
您现在创建自由函数来创建指向此类结构的指针(不是实例,因为您看不到它的完整定义)并通过将此类指针及其所有方法作为参数来处理此类指针及其所有方法。
请注意,如果该类位于命名空间中,您将无法执行此操作,因此请创建您自己的仅包含该成员的结构,并改用该“包装器”。
对于所有 C 函数。仅在标题中,放入
#ifdef __cplusplus
extern "C" {
#endif
// all your functions
#ifdef __cplusplus
}
#endif
典型的包装器如下所示:
---- 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);
}