Для внешнего "C" или не для внешнего "C" [g ++ против cl] - PullRequest
0 голосов
/ 25 января 2019

Я сравниваю Численные рецепты four1.c с БПФ Наюки . Обе версии C, но я использую драйвер C ++. Для сравнения я собираю (или, точнее, связываю) оба файла в исполняемый файл с CL.exe и g ++. Похоже, что эти двое борются из-за того, использовать ли extern «C» для функции four1, но ни один из них не заботится о функции Наюки. Я сделал заголовочный файл для 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

И это то, что делает g ++, если используется extern "C":

/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. По крайней мере, для этого файла. Для кода Наюки такой проблемы не существует.

Я попытался пересмотреть заголовочный файл, как было рекомендовано, так что теперь вот 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 ++ не работает.

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Используйте gcc для компиляции four1.c, , а не g++.

0 голосов
/ 25 января 2019

Посмотрите практически на любой системный заголовочный файл 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 ++.За исключением, конечно, вы не должны использовать начальные подчеркивания, так как они зарезервированы для системных вещей.

...