C和C++通过extern "C"进行链接

5

我有一个C++函数,在.h文件中定义,.cpp文件中实现如下:

extern "C" void func(bool first, float min, float* state[6], float* err[6][6])
{
    //uses vectors and classes and other C++ constructs
}

我该如何在C文件中调用函数?我应该如何设置文件结构/Makefile以编译它?谢谢!

1
该函数是否在头文件中定义(即包括{ }之间的部分)或者是在头文件中声明(即以);结尾)?如果是前者,您需要编写另一个头文件,省略extern "C"{ }这两部分,然后将其用于程序的C部分。 - DevSolar
我觉得我没有清楚地解释我的问题。我会用更好的例子再试一次。 - CodeKingPlusPlus
我将删除并重新发布。 - CodeKingPlusPlus
4个回答

11

您可以按照普通方式从C中调用该函数。 但是,您需要将extern "C"包装在预处理器宏中,以防止C编译器看到它:

您可以正常地从C中调用该函数。不过,为了防止C编译器看到extern "C",您需要将其包装在预处理器宏中:

#ifndef __cplusplus
extern "C"
#endif
void func(bool first, float min, float* state[6], float* err[6][6]);

假设您正在使用GCC,则使用gcc编译C代码,使用g++编译C ++代码,然后使用g++链接。


我从gcc那里得到了错误提示,说我的C文件包含了使用向量的函数定义文件,因此无法包含向量。 - CodeKingPlusPlus
1
你也许只想使用g++编译整个程序?当你构建.dll并希望链接它而不必知道其混淆名称时,我通常在C++代码中看到extern "C"。 - Josh Petitt
3
您好,@CodeKingPlusPlus 问:“什么是链接?”,我担心我们在这里遇到了问题……请查看GCC手册中的“-c”选项以及“链接”的含义。否则,您在这里得到的任何答案都没有意义。 - DevSolar
1
@JoshPetitt:在这种情况下,任何类型的共享库(.so.dll等)。因为这是GCC,我认为它可能是Linux,即使不是,其他平台上的GCC仍然使用.so。(Mac无论如何都使用它,在Windows上需要类似Cygwin的层)。 - Linuxios
2
答案不应该是 #ifdef __cplusplus 吗? - Osman-pasha
显示剩余2条评论

4

要在C语言中调用它,你只需要正常调用即可。因为你使用了extern "C"告诉编译器使用C语言的调用约定和ABI,所以你可以正常地调用它:

func(args);

要编译,请使用以下代码进行C++:

g++ -c -o myfunc.o myfunc.cpp

然后这是针对C盘的操作:
gcc -c -o main.o somec.c

以下是链接:

g++ -o main main.o myfunc.o

确保函数的 C++ 头文件仅使用 C 构造。因此,请在 .cpp 文件中包含诸如 <vector> 等内容。


@CodeKingPlusPlus:-c 选项告诉编译器仅将您的代码编译为中间目标代码文件(.o),然后通过排除 -c 选项将它们链接在一起形成可执行文件。目标文件允许您结合 C 和 C++,并将项目的不同部分分开。 它们还允许您仅编译代码的小部分,这对于像 make 的大型项目和系统至关重要。 - Linuxios
谢谢!当我运行最后的编译命令(gcc -o main main.o myfunc.o)时,它失败了,并告诉我在myfunc.cpp中包含的文件有未定义的引用。 - CodeKingPlusPlus
@CodeKingPlusPlus:针对哪些文件?确切的信息是什么? - Linuxios

3

使用C语言调用它:

func(/* put arguments here */);

通过使用extern "C",您要求编译器不要混淆您的名称。否则,在链接器之前,C++编译器会倾向于混淆它们(即添加附加符号使它们唯一)。
您还需要确保设置为使用C调用约定。

1
非常挑剔地说,它禁用了*c++*的名称修饰,而不是所有的名称修饰(在某些情况下,c使用名称修饰)。http://blogs.msdn.com/b/oldnewthing/archive/2012/05/25/10310148.aspx - BoBTFish
1
@BoBTFish :-) 是的,这就是我为什么说“询问”编译器的原因。感谢您的澄清和超链接。+1 - Josh Petitt

1
//header file included from both C and C++ files

#ifndef __cplusplus
#include <stdbool.h> // for C99 type bool
#endif

#ifdef __cplusplus
extern "C" {
#endif

void func(bool first, float min, float* state[6], float* err[6][6]);

#ifdef __cplusplus
} // extern "C"
#endif

// cpp file
#include "the_above_header.h"
#include <vector>

extern "C" void func(bool first, float min, float* state[6], float* err[6][6]);
{
    //uses vectors and classes and other C++ constructs
}

// c file
#include "the_above_header.h"

int main() {
    bool b;
    float f;
    float *s[6];
    float *err[6][6];
    func(b,f,s,err);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接