使用extern“C”在c ++程序中包含标题时出错

error when using extern “C” to include a header in c++ program

我正在进行一个学校项目,这需要与牧羊犬合作。sheepdog提供了一个C API,使您能够连接到sheepdog服务器。首先,我用以下内容创建C源文件(test.c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include"sheepdog/sheepdog.h"
#include <stdio.h>
int main()
{
struct sd_cluster *c = sd_connect("192.168.1.104:7000");
if (!c) {
    fprintf(stderr,"failed to connect %m
"
);
    return -1;
}else{
    fprintf(stderr,"connected successfully %m
"
);
}
    return 0;
}

然后我使用以下命令编译,没有任何错误

gcc -o test test.c -lsheepdog -lpthread

但是我需要用C++项目来使用它,所以我创建了一个CPP文件(test .CPP),内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extern"C"{
#include"sheepdog/sheepdog.h"
}
#include <stdio.h>
int main()
{
    struct sd_cluster *c = sd_connect("192.168.1.104:7000");
    if (!c) {
       fprintf(stderr,"failed to connect %m
"
);
       return -1;
    }else{
       fprintf(stderr,"connected successfully %m
"
);
    }
    return 0;
}

现在,当我使用以下命令编译时:

g++ -o test test.cpp -lsheepdog -lpthread

我得到这个错误:compilation error message


你不能只在一个报头上包EDCOX1×0,并期望它在C++程序中编译。例如,头EDOCX1 OR 1使用一个名为EDCOX1(2)的参数;这是C++中的关键字,所以没有办法编译成C++。该库不是设计为C++调用的。


我同意@petebecker。从谷歌周围的快速浏览,我不确定是否有一个简单的解决方案。牧羊犬使用的C特征和名称不能很好地移植到C++中。你可能需要对牧羊犬进行相当广泛的黑客攻击。例如:

  • inline函数从sheepdog_proto.h移到新的C文件中,保留原型。这应该考虑到offsetof错误,例如,在这个答案中讨论的错误。
  • #define new not_a_keyword_newsheepdog/sheepdog.h

为了让它编译,你还需要做任何其他具体的改变。这里的专家有更多的建议。


由于牧羊犬没有被设计成可用于C++,所以你应该用C语言构建一个小包装器来调用牧羊犬的函数,并且只从C++代码中调用包装器。编写这样一个包装器的一些提示:

  • void *非常适合传递不透明的指针。
  • 提取器可以帮助访问命名错误的成员。如果结构有一个名为new的成员(类型为t),则可以编写:

    1
    T getNew(void *otherstruct); // declaration in .h

    1
    2
    3
    T getNew(void *otherstruct) {        // implementation in a c file
        return ((ActualStruct *) otherstruct)->new;
    }

根据牧羊犬的复杂性(我不知道)和您想要使用的部分,它可能是或不是一个可接受的解决方案。但这是我试图面对这样一个问题的方式。

无论如何,链接器允许混合在C和C++中编译的模块,无论是静态链接还是动态链接。