Я компилирую код, созданный с помощью 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.)

Однако я отказываюсь от всего этого решения, потому что я нашел более простой способ получить данные с моей IP-камеры с помощью OpenCV и ffmpeg. Так что я больше не буду тестировать.

Спасибо всем за помощь.

0
Sheric 23 Дек 2015 в 19:02

2 ответа

Лучший ответ

Я подозреваю, что проблема в том, что вы пытаетесь связать код 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);
}

Это предотвратит искажение вложенных функций, чтобы можно было правильно найти и связать их ссылку в объектном файле. Дополнительную информацию можно найти здесь.

3
Community 23 Май 2017 в 10:27

Эта проблема возникла из-за попытки связать код C с кодом C ++.

Допустим, у вас есть wssapi.c wssapi.h main.cpp. В вашем main.cpp сделайте это

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

А не только

#include "wssapi.h"
1
Danh 23 Дек 2015 в 23:44