使用extern“C”在c ++程序

时间:2016-08-19 14:08:41

标签: c++ c extern

我正在开展一个需要与sheepdog合作的学校项目。 Sheepdog提供了一个c api,可以连接到牧羊犬服务器。 首先,我使用以下内容创建c源文件(test.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\n");
    return -1;
}else{
    fprintf(stderr, "connected successfully %m\n");
}
    return 0;
}

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

  

gcc -o test test.c -lsheepdog -lpthread

但我需要的是将它与c ++项目一起使用,所以我创建了一个cpp文件(test.cpp),其中包含以下内容:

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\n");
       return -1;
    }else{
       fprintf(stderr, "connected successfully %m\n");
    }
    return 0;
}

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

  

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

我收到此错误:compilation error message

3 个答案:

答案 0 :(得分:6)

您不能将extern "C"包裹在标题周围,并期望它在C ++程序中编译。例如,标头sheepdog_proto.h使用名为new的参数;这是C ++中的关键字,因此无法以C ++编译。该库不是为从C ++调用而设计的。

答案 1 :(得分:1)

我同意@PeteBecker。通过快速浏览Google,我不确定是否有一个简单的解决方案。 Sheepdog使用的C功能和名称不能很好地适应C ++。你可能需要相当广泛地攻击牧羊犬。例如:

  • inline函数从sheepdog_proto.h移出到新的C文件中,将原型保留在原位。这应该处理offsetof错误,例如this answer中讨论的错误。
  • #define new not_a_keyword_new
  • sheepdog/sheepdog.h

以及为了使其编译而必须进行的任何其他特定更改。来自专家的更多建议here

答案 2 :(得分:0)

由于牧羊犬的设计不能用于C ++,你应该用C语言构建一个小包装器来调用牧羊犬的函数,并只从你的c ++代码中调用包装器。写一些包装器的一些提示:

  • void *非常适合传递不透明指针
  • 提取器可以帮助访问命名严重的成员。如果一个struct有一个名为new的成员(类型为T),你可以写:

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

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

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

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