对同一文件中定义的函数的未定义引用
Undefined reference to a function defined in the same file
我正在编译gsoap生成的代码,我也应该编译一些gsoap在/usr/share/gsoap/plugin/
中提供的文件。
问题是在链接步骤中,出现未定义引用错误:
wsseapi.o: In function `soap_wsse_verify_Timestamp':
wsseapi.cpp:(.text+0xf64): undefined reference to `soap_wsa_sender_fault_subcode'
...同一符号还有更多内容。
然而,该符号与使用它的 soap_wsse_verify_Timestamp
在同一文件中定义,当我使用 readelf 检查目标文件时,该符号在其中定义:
$ readelf -Ws wsseapi.o |grep soap_wsa_sender_fault_subcode
164: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND soap_wsa_sender_fault_subcode
原始文件中的函数定义如下:
/**
@fn int soap_wsse_verify_Timestamp(struct soap *soap)
@brief Verifies the Timestamp/Expires element against the current time.
@param soap context
@return SOAP_OK or SOAP_FAULT with wsse:FailedAuthentication fault
Sets wsse:FailedAuthentication fault if wsu:Timestamp is expired. The
SOAP_WSSE_CLKSKEW value is used as a margin to mitigate clock skew. Keeps
silent when no timestamp is supplied or no expiration date is included in the
wsu:Timestamp element.
*/
int
soap_wsse_verify_Timestamp(struct soap *soap)
{ _wsu__Timestamp *timestamp = soap_wsse_Timestamp(soap);
DBGFUN("soap_wsse_verify_Timestamp");
/* if we have a timestamp with an expiration date, check it */
if (timestamp && timestamp->Expires)
{ time_t now = time(NULL), expired;
soap_s2dateTime(soap, timestamp->Expires, &expired);
if (expired + SOAP_WSSE_CLKSKEW <= now)
{ const char *code = soap_wsu__tTimestampFault2s(soap, wsu__MessageExpired);
return soap_wsse_sender_fault_subcode(soap, code, "Message has expired", timestamp->Expires);
}
}
return SOAP_OK;
}
和
/**
@fn int soap_wsse_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
@brief Sets sender SOAP Fault (sub)code for server fault response.
@param soap context
@param[in] faultsubcode sub code string
@param[in] faultstring fault string
@param[in] faultdetail detail string
@return SOAP_FAULT
*/
int
soap_wsse_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
{
#if defined(SOAP_WSA_2003) || defined(SOAP_WSA_2004) || defined(SOAP_WSA_200408) || defined(SOAP_WSA_2005)
return soap_wsa_sender_fault_subcode(soap, faultsubcode, faultstring, faultdetail);
#else
return soap_sender_fault_subcode(soap, faultsubcode, faultstring, faultdetail);
#endif
}
最后,
/**
@fn int soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
@brief Sets sender SOAP Fault (sub)code for server fault response.
@param soap context
@param[in] faultsubcode sub code string
@param[in] faultstring fault string
@param[in] faultdetail detail string
@return SOAP_FAULT
*/
int
soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
{ return soap_wsa_fault_subcode(soap, 1, faultsubcode, faultstring, faultdetail);
}
我的问题是,当符号在同一个文件中定义并且可以在同一个目标文件中找到时,怎么会出现未定义的引用错误。
谢谢。
编辑:
这是 cpp 文件顶部包含的头文件中的定义部分:
int soap_wsa_request(struct soap *soap, const char *id, const char *to, const char *action);
int soap_wsa_add_From(struct soap *soap, const char *endpoint);
int soap_wsa_add_NoReply(struct soap *soap);
int soap_wsa_add_ReplyTo(struct soap *soap, const char *endpoint);
int soap_wsa_add_FaultTo(struct soap *soap, const char *endpoint);
int soap_wsa_add_RelatesTo(struct soap *soap, const char *endpoint);
const char *soap_wsa_From(struct soap *soap);
const char *soap_wsa_ReplyTo(struct soap *soap);
const char *soap_wsa_FaultTo(struct soap *soap);
const char *soap_wsa_RelatesTo(struct soap *soap);
int soap_wsa_check(struct soap *soap);
int soap_wsa_reply(struct soap *soap, const char *id, const char *action);
int soap_wsa_fault_subcode(struct soap *soap, int flag, const char *faultsubcode, const char *faultstring, const char *faultdetail);
int soap_wsa_fault_subcode_action(struct soap *soap, int flag, const char *faultsubcode, const char *faultstring, const char *faultdetail, const char *action);
int soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail);
int soap_wsa_sender_fault_subcode_action(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail, const char *action);
int soap_wsa_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail);
int soap_wsa_receiver_fault_subcode_action(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail, const char *action);
int soap_wsa_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail);
int soap_wsa_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail);
更新:
问题似乎是由于 C++ 和 C 之间的链接问题(正如您在答案中看到的那样)。 gsoap 文件中存在一个悖论,因为在 C 源代码中使用了一个自动生成的头文件,wsseapi.c
使用了 C++ 功能。如果我能解决这个问题,那么我认为编译和链接 wsseapi.c 也可以解决这个问题(正如评论中提到的那样,缺少的函数实际上是在 C 源文件中定义的。)
但是,我放弃了整个解决方案,因为我找到了一种更简单的方法来使用 OpenCV
和 ffmpeg
从我的 IP 摄像机获取数据。所以我不会再测试了。
谢谢大家的帮助。
我怀疑的问题是您正试图 link 使用 C++ 编写一些 C 代码。这可能会导致 linking 错误,原因是 C++ 中的名称与 C 相比是如何被破坏的。
要解决此类问题,您应该将从 C 源文件编译的函数包装在 extern
范围内:
extern "C" {
int soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail);
}
这将防止包含的函数被破坏,以便可以正确找到它们在目标文件中的引用并 linked。您可以找到更多信息 here.
发生此问题是因为您试图 link C 代码与 C++ 代码。
假设您有 wssapi.c
wssapi.h
main.cpp
。在你的main.cpp
中这样做
extern "C" {
#include "wssapi.h"
}
而不只是
#include "wssapi.h"
我正在编译gsoap生成的代码,我也应该编译一些gsoap在/usr/share/gsoap/plugin/
中提供的文件。
问题是在链接步骤中,出现未定义引用错误:
wsseapi.o: In function `soap_wsse_verify_Timestamp':
wsseapi.cpp:(.text+0xf64): undefined reference to `soap_wsa_sender_fault_subcode'
...同一符号还有更多内容。
然而,该符号与使用它的 soap_wsse_verify_Timestamp
在同一文件中定义,当我使用 readelf 检查目标文件时,该符号在其中定义:
$ readelf -Ws wsseapi.o |grep soap_wsa_sender_fault_subcode
164: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND soap_wsa_sender_fault_subcode
原始文件中的函数定义如下:
/**
@fn int soap_wsse_verify_Timestamp(struct soap *soap)
@brief Verifies the Timestamp/Expires element against the current time.
@param soap context
@return SOAP_OK or SOAP_FAULT with wsse:FailedAuthentication fault
Sets wsse:FailedAuthentication fault if wsu:Timestamp is expired. The
SOAP_WSSE_CLKSKEW value is used as a margin to mitigate clock skew. Keeps
silent when no timestamp is supplied or no expiration date is included in the
wsu:Timestamp element.
*/
int
soap_wsse_verify_Timestamp(struct soap *soap)
{ _wsu__Timestamp *timestamp = soap_wsse_Timestamp(soap);
DBGFUN("soap_wsse_verify_Timestamp");
/* if we have a timestamp with an expiration date, check it */
if (timestamp && timestamp->Expires)
{ time_t now = time(NULL), expired;
soap_s2dateTime(soap, timestamp->Expires, &expired);
if (expired + SOAP_WSSE_CLKSKEW <= now)
{ const char *code = soap_wsu__tTimestampFault2s(soap, wsu__MessageExpired);
return soap_wsse_sender_fault_subcode(soap, code, "Message has expired", timestamp->Expires);
}
}
return SOAP_OK;
}
和
/**
@fn int soap_wsse_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
@brief Sets sender SOAP Fault (sub)code for server fault response.
@param soap context
@param[in] faultsubcode sub code string
@param[in] faultstring fault string
@param[in] faultdetail detail string
@return SOAP_FAULT
*/
int
soap_wsse_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
{
#if defined(SOAP_WSA_2003) || defined(SOAP_WSA_2004) || defined(SOAP_WSA_200408) || defined(SOAP_WSA_2005)
return soap_wsa_sender_fault_subcode(soap, faultsubcode, faultstring, faultdetail);
#else
return soap_sender_fault_subcode(soap, faultsubcode, faultstring, faultdetail);
#endif
}
最后,
/**
@fn int soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
@brief Sets sender SOAP Fault (sub)code for server fault response.
@param soap context
@param[in] faultsubcode sub code string
@param[in] faultstring fault string
@param[in] faultdetail detail string
@return SOAP_FAULT
*/
int
soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
{ return soap_wsa_fault_subcode(soap, 1, faultsubcode, faultstring, faultdetail);
}
我的问题是,当符号在同一个文件中定义并且可以在同一个目标文件中找到时,怎么会出现未定义的引用错误。
谢谢。
编辑: 这是 cpp 文件顶部包含的头文件中的定义部分:
int soap_wsa_request(struct soap *soap, const char *id, const char *to, const char *action);
int soap_wsa_add_From(struct soap *soap, const char *endpoint);
int soap_wsa_add_NoReply(struct soap *soap);
int soap_wsa_add_ReplyTo(struct soap *soap, const char *endpoint);
int soap_wsa_add_FaultTo(struct soap *soap, const char *endpoint);
int soap_wsa_add_RelatesTo(struct soap *soap, const char *endpoint);
const char *soap_wsa_From(struct soap *soap);
const char *soap_wsa_ReplyTo(struct soap *soap);
const char *soap_wsa_FaultTo(struct soap *soap);
const char *soap_wsa_RelatesTo(struct soap *soap);
int soap_wsa_check(struct soap *soap);
int soap_wsa_reply(struct soap *soap, const char *id, const char *action);
int soap_wsa_fault_subcode(struct soap *soap, int flag, const char *faultsubcode, const char *faultstring, const char *faultdetail);
int soap_wsa_fault_subcode_action(struct soap *soap, int flag, const char *faultsubcode, const char *faultstring, const char *faultdetail, const char *action);
int soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail);
int soap_wsa_sender_fault_subcode_action(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail, const char *action);
int soap_wsa_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail);
int soap_wsa_receiver_fault_subcode_action(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail, const char *action);
int soap_wsa_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail);
int soap_wsa_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail);
更新:
问题似乎是由于 C++ 和 C 之间的链接问题(正如您在答案中看到的那样)。 gsoap 文件中存在一个悖论,因为在 C 源代码中使用了一个自动生成的头文件,wsseapi.c
使用了 C++ 功能。如果我能解决这个问题,那么我认为编译和链接 wsseapi.c 也可以解决这个问题(正如评论中提到的那样,缺少的函数实际上是在 C 源文件中定义的。)
但是,我放弃了整个解决方案,因为我找到了一种更简单的方法来使用 OpenCV
和 ffmpeg
从我的 IP 摄像机获取数据。所以我不会再测试了。
谢谢大家的帮助。
我怀疑的问题是您正试图 link 使用 C++ 编写一些 C 代码。这可能会导致 linking 错误,原因是 C++ 中的名称与 C 相比是如何被破坏的。
要解决此类问题,您应该将从 C 源文件编译的函数包装在 extern
范围内:
extern "C" {
int soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail);
}
这将防止包含的函数被破坏,以便可以正确找到它们在目标文件中的引用并 linked。您可以找到更多信息 here.
发生此问题是因为您试图 link C 代码与 C++ 代码。
假设您有 wssapi.c
wssapi.h
main.cpp
。在你的main.cpp
中这样做
extern "C" {
#include "wssapi.h"
}
而不只是
#include "wssapi.h"