【问题标题】:Undefined reference to a function defined in the same file对同一文件中定义的函数的未定义引用
【发布时间】:2015-12-23 16:02:36
【问题描述】:

我正在编译一个用gsoap生成的代码,我也应该编译/usr/share/gsoap/plugin/中gsoap提供的一些文件。

问题是在链接步骤中,我得到未定义的引用错误:

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 也可以解决这个问题(正如 cmets 中的某人所提到的,缺失的函数实际上是在 C 源文件中定义的。)

但是,我放弃了整个解决方案,因为我找到了一种更简单的方法来使用 OpenCVffmpeg 从我的 IP 摄像机获取数据。所以我不会再测试了。

感谢大家的帮助。

【问题讨论】:

  • 它似乎尝试再次链接 C 样式函数,但您将其编译为 C++ 函数。此错误“未定义对 `soap_wsa_sender_fault_subcode' 的引用”看起来像 C 函数签名
  • 也许吧!那边gsoap提供了两个文件,一个是c,另一个是cpp文件,功能相同,可能转换成cpp的时候遗漏了一些改动。
  • 你用什么命令行编译&链接?
  • 重击!我正在用 qbuild、g++ 和 Ubuntu 14.04 编译代码
  • 您确定soap_wsa_sender_fault_subcode 是在同一个文件中定义的吗?在 github 的当前源中,它在 wsapi.c 中定义,但在 wsseapi.cpp 中没有定义。

标签: c++ linker undefined-reference gsoap


【解决方案1】:

我怀疑的问题是您正在尝试将一些 C 代码与 C++ 链接。与 C 相比,这可能会导致由于 C++ 中的名称被破坏而导致的链接错误。

要解决此类问题,您应该将从 C 源文件编译的函数包装在 extern 范围内:

extern "C" {
  int soap_wsa_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail);
}

这将防止封闭的函数被破坏,以便可以正确找到和链接它们在目标文件中的引用。您可以找到更多信息here

【讨论】:

  • 围绕整个 cpp 文件这样做会给我很多错误,例如 /usr/include/c++/4.8/bits/istream.tcc:83:3: error: template with C linkage template&lt;typename _CharT, typename _Traits&gt;。另一方面,我不想更改库文件!有更好的办法吗?源文件名为 .cpp ,那里还有另一个同名的 .c 文件,但是当我包含它时,在另一个头文件(用脚本生成)中包含了向量库,它给了我一个未解决的包含错误。跨度>
  • 您不能围绕整个 CPP 文件执行此操作,您必须围绕来自 C 环境的方法的前向声明执行此操作。这是正确的解决方案,我从不介意找到一个 hacky 解决方法,因为不需要一个。
  • 嗯,我错过的函数是在cpp中定义的!
  • @Sheric 你只需要extern "C"函数声明;;然后自动应用于定义
【解决方案2】:

出现此问题是因为您尝试将 C 代码与 C++ 代码链接。

假设你有wssapi.cwssapi.hmain.cpp。在您的main.cpp 中执行此操作

extern "C" {
    #include "wssapi.h"
}

而不仅仅是

#include "wssapi.h"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多