[英]Call C++ function from (C) header file gives linker error
I am integrating a library (lwip) and I want to reroute the logging mechanism from printf
to something I wrote myself (which logs directly to my uart).我正在集成一个库(lwip),我想将日志记录机制从
printf
重新路由到我自己编写的东西(直接记录到我的 uart)。
In some header file the following code exists在某些 header 文件中存在以下代码
/** Platform specific diagnostic output.\n
* Note the default implementation pulls in printf, which may
* in turn pull in a lot of standard libary code. In resource-constrained
* systems, this should be defined to something less resource-consuming.
*/
#ifndef LWIP_PLATFORM_DIAG
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#include <stdio.h>
#include <stdlib.h>
#endif
I replaced this line我换了这条线
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
with和
#define LWIP_PLATFORM_DIAG(x) do {logLineToUart x;} while(0)
I am using the same signature for my function as the printf
signature:我为我的 function 使用与
printf
签名相同的签名:
void logLineToUart(const char * log, ...);
And I placed that function in my own header lwiplogging.h
, which I include in the header which defines LWIP_PLATFORM_DIAG
我将 function 放在我自己的 header
lwiplogging.h
中,我将其包含在定义 LWIP_PLATFORM 的LWIP_PLATFORM_DIAG
And, I implement the function in a C++ file:而且,我在 C++ 文件中实现了 function:
void logLineToUart(const char * log, ...)
{
uart3.Write(log);
uart3.Write("\r\n");
}
NOTE: uart3 is an object of my Uart
class.注意:uart3 是我的
Uart
class 的 object。 Hence it's C++ code.因此它是 C++ 代码。 I suspect this is the problem, but I can't figure out how to correct my error.
我怀疑这是问题所在,但我不知道如何纠正我的错误。 Adding
extern "C"
to the function doesn't seem to solve it either.将
extern "C"
添加到 function 似乎也不能解决它。
The linker error I get:我得到的 linker 错误:
Linking .pio\build\nucleo_f446ze\firmware.elf
.pio/build/nucleo_f446ze/lib997/lwip/api/api_lib.o: In function `netconn_send':
api_lib.c:(.text.netconn_send+0x26): undefined reference to `logLineToUart'
.pio/build/nucleo_f446ze/lib997/lwip/api/sockets.o: In function `tryget_socket_unconn_nouse':
sockets.c:(.text.tryget_socket_unconn_nouse+0xa): undefined reference to `logLineToUart'
.pio/build/nucleo_f446ze/lib997/lwip/api/sockets.o: In function `get_socket':
sockets.c:(.text.get_socket+0x14): undefined reference to `logLineToUart'
.pio/build/nucleo_f446ze/lib997/lwip/api/sockets.o: In function `lwip_connect':
sockets.c:(.text.lwip_connect+0x22): undefined reference to `logLineToUart'
sockets.c:(.text.lwip_connect+0x38): undefined reference to `logLineToUart'
.pio/build/nucleo_f446ze/lib997/lwip/api/sockets.o:sockets.c:(.text.lwip_connect+0x7e): more undefined references to `logLineToUart' follow
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\nucleo_f446ze\firmware.elf] Error 1
What am I doing wrong?我究竟做错了什么?
UPDATE更新
The error I get when I declare the function as extern "C"当我将 function 声明为 extern "C" 时出现的错误
UPDATE 2:更新 2:
This does compile:这确实编译:
#ifdef __cplusplus
extern "C" {
void logLineToUart(const char * log, ...);
#endif
void logLineToUart(const char * log, ...);
#ifdef __cplusplus
}
#endif
extern "C" void logLineToUart(const char * log, ...);
You need to tell it to make the name C-linker compatible the first time it is seen.您需要告诉它在第一次看到它时使名称 C-linker 兼容。
The extern "C"
is only when compiling as C++. extern "C"
仅在编译为 C++ 时。 It is not legal syntax in C. C 中的语法不合法。 You can use
extern
by itself (it is implied if you leave it off).您可以单独使用
extern
(如果您不使用它,则暗示它)。
That's not very friendly... C++ accommodates sharing header files with C by accepting syntax that would not apply to C++, just to make it easy to use the same header file contents. That's not very friendly... C++ accommodates sharing header files with C by accepting syntax that would not apply to C++, just to make it easy to use the same header file contents. In particular, using
(void)
for empty parameter lists (which is "an abomination") and allowing a comma in variadic function parameter lists ( (int x...)
is how C++ originally defined it; when the same feature got incorporated into ANSI C they used (int x, ...)
with a superfluous comma that is not needed by the grammar.) C++ compilers accept both of these to make it easier to consume C headers...特别是,将
(void)
用于空参数列表(这是“可憎的”)并允许在可变参数 function 参数列表中使用逗号( (int x...)
是 C++ 最初定义它的方式;当相同的功能被合并到他们使用的ANSI C (int x, ...)
带有语法不需要的多余逗号。)C++ 编译器接受这两者,以便更容易使用 Z0D61F8370CAD1D412F80B84D14 头文件...
But, you have to add extern "C"
around everything.但是,您必须在所有内容周围添加
extern "C"
。 This introduces conditional compilation anyway, even though C++ accepts the C syntax.这无论如何都会引入条件编译,即使 C++ 接受 C 语法。 Note that for a single declaration,
extern int foo (int);
请注意,对于单个声明,
extern int foo (int);
the extern
is allowed and implied if you leave it out.如果您将其排除在外,则
extern
是允许的并且是隐含的。 If the C compiler allowed the linkage specification even though only "C" is available, it would make life easier.如果 C 编译器允许链接规范,即使只有“C”可用,它也会使生活更轻松。 Note that in most cases, the C and C++ implementation are the same compiler suite, and often one language supports some features of the other as extensions.
请注意,在大多数情况下,C 和 C++ 实现是相同的编译器套件,并且通常一种语言支持另一种语言的某些功能作为扩展。 It would be cool if
gcc
etc. supported extern "C++"
in C mode, since that code base certainly does know how the name encodes the parameters.如果
gcc
等在 C 模式下支持extern "C++"
会很酷,因为该代码库当然知道名称如何编码参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.