Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何调用用C++;从C?_C++_C_Linker_Static Linking - Fatal编程技术网

C++ 如何调用用C++;从C?

C++ 如何调用用C++;从C?,c++,c,linker,static-linking,C++,C,Linker,Static Linking,在我看来,这似乎是一个不假思索的问题,但我找不到任何反对或支持它的信息 从DeangLink等的观点来看,我不认为这是一个大问题,但我想不出,我如何编写一个小C程序,它调用一个小的C++库函数。 我现在在linux上,尝试使用静态绑定 这肯定是很多人遇到的问题,或者是很多书的封面,但我觉得自己就像一个盲人阿甘正坐在这个问题面前。有趣的是,在这方面也没有这样的问题 我甚至不知道这是否可行,更不用说如何做到了。从需求的角度来看,这是一个问题。用C++来调用C. 在C++中是不规范的,因为它被认为太依

在我看来,这似乎是一个不假思索的问题,但我找不到任何反对或支持它的信息

从DeangLink等的观点来看,我不认为这是一个大问题,但我想不出,我如何编写一个小C程序,它调用一个小的C++库函数。 我现在在linux上,尝试使用静态绑定

这肯定是很多人遇到的问题,或者是很多书的封面,但我觉得自己就像一个盲人阿甘正坐在这个问题面前。有趣的是,在这方面也没有这样的问题


我甚至不知道这是否可行,更不用说如何做到了。

从需求的角度来看,这是一个问题。用C++来调用C.</P>

在C++中是不规范的,因为它被认为太依赖平台。结果是,虽然你可以通过查看链接器输出来找出C++方法的名称,但是没有一种可移植的方法来找到函数的C++的“实际”可链接名称。

< P>如果C++库不提供C接口,那么你就不能。 如果是,请使用C接口


如果您是作者,请使用
extern“C”
功能

> P>,通常需要强制C++编译器为导出函数使用C链接构建库。 您可以通过对标题执行以下操作来完成此操作:

#ifdef __cplusplus
extern "C" {
#endif

void func(void);

/* ... Other function defs go here ... */

#ifdef __cplusplus
}
#endif

正常情况下,链接器会对函数进行C++名称的修改,从而使C链接器无法找到它们。代码>外部“C”强制它不这样做。您需要将其包装在

#ifdef
中,因为
extern“C”
在C中无效

更新


正如Charles Salvia在下面的评论中所说的,你需要确保没有异常通过接口来实现,因为C++没有处理它们的能力(至少不是平台无关的方式)。换句话说,在Linux上编写绑定.< /p> ,可以用命令

获得C++函数的已损坏名称。
nm my-tiny-c++lib.a
从C中调用该函数,但不要期望该技巧是可移植的


<> > >编辑< /St>:然后必须使用G+链接,或者用GCC -LSTDC++/P>> P>可以在C++的任何具有C++ C++库的库上编写C包装器。包装器应该用C++编写。 <>你甚至可以使用C++类。您可以将它们主动声明为struct。如果执行此操作,某些编译器将发出警告,但您可能可以禁用此警告或忽略它

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

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

对于所有的C函数。仅在标题中,将

#ifdef __cplusplus
extern "C" {
#endif

// all your functions

#ifdef __cplusplus
}
#endif

典型的包装器如下所示:

----a类水电站----

----类a_包装器.h----

----类a_包装器.cpp----

#包括“a类水电站”
int wrap_A_foo(结构wrap_A*obj,双p){
返回(静态)->foo(p);
}
双环绕条(结构环绕*对象,整数x,整数y){
返回(静态)->bar(x,y);
}

<代码> >注意,代码> FUNC不会抛出任何未通过C代码传播的C++异常。@查尔斯SalVIEA,好主意,但如何比C++中的异常异常更坏,它们都会导致崩溃。建议将函数声明更改为<代码>无效FUNC(无效);代码> C++中的条件定义<代码> >定义NoPosivs/Cuth>和Cux>mode@mikerobi它的区别在于:(1)C++中的一个未被排除的异常不会引起未定义的行为,它只是终止程序,谁知道在J2+平台上,C代码中传播的异常异常会发生什么,更重要的是(2)在C++中,可以捕获更高级别的异常(例如,在<代码>主代码>代码>中),而使用C++代码的C程序不能在任何地方捕获异常。因此,C接口不能有效地抛出异常,而不能有效地返回<代码> STD::String 。@查尔斯SalVaI: C++中的一个未被排除的异常不会导致崩溃(这表明应用程序已经达到了一个坏状态)。未捕获的异常会导致正常程序终止。一些操作系统能够检测通过异常退出的应用程序,并将情况通知用户。注意:应该始终在main中捕获异常,否则调用堆栈可能不会展开。一旦您确定调用堆栈已解除,然后重新抛出异常以使您的操作系统启动。you/can/,这非常痛苦,并且非常非常依赖于编译器,包括编译器版本。+1获得最普遍适用和灵活的答案。你可以做到这一点,即使你没有C++库的来源,你可以在绑定中构造对象并调用它们。这是一个非常有趣的黑客来检查我正在战斗的战斗。我知道nm,并且已经检查了lib来搜索任何线索,但是没有用这个名字调用函数的想法。我曾想过外部“C”
,但我错误地推断,这只是为了相反的目的。当然,这很有魅力,
#include "class_a_wrapper"

class A {
     public:
     int foo(double p);
     double bar(int x, int y);
}
#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
#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);
}