to extern“C”或not extern extern“C”[g ++ vs cl]

问题描述 投票:3回答:2

我正在将Numerical Recipes four1.c与Nayuki's FFT进行比较。两者都是C版本,但我使用的是C ++驱动程序。为了进行比较,我正在使用CL.exe和g ++编译(或更恰当地说,链接)到可执行文件中。两人似乎都在争论是否使用extern“C”作为four1功能,但似乎都不关心Nayuki的。我为four1制作了一个头文件,检查_WIN32是为了适当切换,它可以工作,但似乎是一个完全不可接受的黑客。我该如何解决这个问题?

这是头文件:

#pragma once
#ifdef _WIN32
extern "C" void four1(float data[], unsigned long nn, int isign);
#else
void four1(float data[], unsigned long nn, int isign);
#endif

这就是CL没有外部“C”的情况:

drvr.obj : error LNK2019: unresolved external symbol "void __cdecl four1(float * const,unsigned long,int)" (?four1@@YAXQAMKH@Z) referenced in function _main
drvr.exe : fatal error LNK1120: 1 unresolved externals

如果使用extern“C”,这就是g ++的作用:

/tmp/ccK1Hb2N.o: In function `main':
drvr.cpp:(.text+0x347): undefined reference to `four1'
collect2: error: ld returned 1 exit status

适用于CL的内容不适用于g ++,适用于g ++的内容在CL中不起作用。至少对于这个文件。 Nayuki代码不存在这样的问题。

我按照建议尝试修改头文件,所以现在这里是dfour1.h:

#pragma once
/* C++ needs to know that types and declarations are C, not C++.  */
#ifdef  __cplusplus
# define __BEGIN_DECLS  extern "C" {
 void dfour1(double data[], unsigned long nn, int isign);
# define __END_DECLS    }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif

g ++很好用。 CL不是。

>cl drvr.cpp dfour1.c fft.c carrier.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

drvr.cpp
Generating Code...
Compiling...
dfour1.c
fft.c
Generating Code...
Compiling...
carrier.cpp
Generating Code...
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:drvr.exe
drvr.obj
dfour1.obj
fft.obj
carrier.obj
drvr.obj : error LNK2019: unresolved external symbol "void __cdecl dfour1(double * const,unsigned long,int)" (?dfour1@@YAXQANKH@Z) referenced in function _main
drvr.exe : fatal error LNK1120: 1 unresolved externals

顺便说一句,如果没有头文件,也会发生同样的情况,我只需添加:

extern "C" void dfour1(double data[], unsigned long nn, int isign);

到drvr.cpp文件,并删除头文件。 CL仅在extern "C"存在时才有效,但g ++没有。而删除extern "C"适用于g ++而不适用于CL。

是的,我知道原始的头文件是错的,这就是问题的关键。当我“正确地”做到这一点时它没有用,因此这个帖子。当我创建一个“不正确”的头文件来检查正在使用哪个编译器时,它工作正常,这是令人讨厌的部分。简单地检查c ++是行不通的。

c++ c g++ cl extern-c
2个回答
6
投票

查看几乎所有系统C头文件,您将看到如下代码:

/* C++ needs to know that types and declarations are C, not C++.  */
#ifdef  __cplusplus
# define __BEGIN_DECLS  extern "C" {
# define __END_DECLS    }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif

__BEGIN_DECLS

// some declarations

__END_DECLS

这是您自己的标题中要遵循的模式,您需要在其中连接C和C ++。当然,除此之外,您不应使用前导下划线,因为它们是为系统内容保留的。


0
投票

使用gcc编译four1.c,而不是g++

© www.soinside.com 2019 - 2024. All rights reserved.