对同一文件中定义的函数的未定义引用

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 源文件中定义的。)

但是,我放弃了整个解决方案,因为我找到了一种更简单的方法来使用 OpenCVffmpeg 从我的 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"