如何调用用 C++ 编写的库从C?

发布于 2024-09-28 22:08:18 字数 257 浏览 3 评论 0原文

在我看来,这似乎是理所当然的事情,但我找不到任何反对或支持它的信息。

从 demangling 等角度来看,我不认为这是一个大问题,但我不知道如何编写一个小小的 C 程序来调用一个小小的 C++ 库中的函数。

我现在在linux上,尝试静态绑定。

这肯定是很多人都遇到过的问题,或者很多书都提到过的问题,但我感觉自己就像一个盲目的阿甘坐在这个问题面前。有趣的是,SO上也没有这样的问题。

我什至不知道这是否可行,更不知道这必须如何完成。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

心房敞 2024-10-05 22:08:18

通常,您需要强制 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 无法处理它们(至少不是独立于平台的方式)。

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).

跨年 2024-10-05 22:08:18

如果 C++ 库不提供 C 接口,那么您就不能。

如果是,则使用 C 接口。

如果您是作者,请使用 extern "C" 功能。 http://www.parashift.com/c++-faq -lite/mixing-c-and-cpp.html

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

隔岸观火 2024-10-05 22:08:18

就个人而言,我会编写一个 C++ 文件来导出使用 C 链接的函数。换句话说,编写一个绑定。

Personally, I'd write a C++ file that exports functions that use C linkage. In other words, write a binding.

╄→承喏 2024-10-05 22:08:18

在 Linux 上,您可以使用命令

nm my-tiny-c++lib.a

Call the function from C by it's mangled name 来获取 C++ 函数的损坏名称,但不要指望这个技巧是可移植的...

编辑:那么您就拥有了使用 g++ 或 gcc -lstdc++ 进行链接

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++

极度宠爱 2024-10-05 22:08:18

从拆解的角度来看,这是一个问题。在要从 C 调用的 C++ 周围使用 extern C

重整和反重整从未在 C++ 中标准化,因为它被认为过于依赖于平台。结果是,虽然您可以通过查看链接器输出来找出 C++ 方法的方法名称,但没有可移植的方法来查找 C++ 函数方法的“真实”可链接名称。

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.

指尖微凉心微凉 2024-10-05 22:08:18

您可以围绕任何具有 C++ API 的 C++ 库编写 C 包装器。包装器应该用 C++ 编写。

您甚至可以使用 C++ 类。您预先将它们声明为结构体。如果您这样做,某些编译器会发出警告,但您可以禁用此警告或忽略它。

现在,您创建自由函数来创建指向此类结构的指针(不是实例,因为您看不到其完整定义),并通过将其作为参数来处理此类指针及其所有方法。

请注意,如果该类位于命名空间中,您将无法执行此操作,因此请创建自己的仅包含该成员的结构并使用该“包装器”。

适用于所有 C 函数。仅在标题中,放置

#ifdef __cplusplus
extern "C" {
#endif

// all your functions

#ifdef __cplusplus
}
#endif

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
太阳公公是暖光 2024-10-05 22:08:18

典型的包装器如下所示:

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

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文