0

MinGWでSASLをコンパイルしようとしていますが、ソースファイルseterror.cには次のように宣言された2つの関数があります。


#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#ifdef HAVE_SYSLOG
#include <syslog.h>
#endif
#include <stdarg.h>
#include <ctype.h>

#include <sasl.h>
#include <saslutil.h>
#include <saslplug.h>
#include "saslint.h"

#ifdef WIN32
/* need to handle the fact that errno has been defined as a function
   in a dll, not an extern int */
# ifdef errno
#  undef errno
# endif /* errno */
#endif /* WIN32 */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

static int _sasl_seterror_usererr(int saslerr)
{
    /* Hide the difference in a username failure and a password failure */
    if (saslerr == SASL_NOUSER)
    return SASL_BADAUTH;

    /* otherwise return the error given; no transform necessary */
    return saslerr;
}

void sasl_seterror(sasl_conn_t *conn,
           unsigned flags,
           const char *fmt, ...)
{
  size_t outlen=0; /* current length of output buffer */
  size_t pos = 0; /* current position in format string */
  size_t formatlen;
  int result;
  sasl_log_t *log_cb = NULL;
  void *log_ctx;
  int ival;
  char *cval;
  va_list ap; /* varargs thing */
  char **error_buf;
  size_t *error_buf_len;

  if(!conn) {
#ifndef SASL_OSX_CFMGLUE
      if(!(flags & SASL_NOLOG)) {
      /* See if we have a logging callback... */
      result = _sasl_getcallback(NULL, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx);
      if (result == SASL_OK && ! log_cb)
          result = SASL_FAIL;
      if (result != SASL_OK)
          return;

      log_cb(log_ctx, SASL_LOG_FAIL,
         "No sasl_conn_t passed to sasl_seterror");
      }  
#endif /* SASL_OSX_CFMGLUE */
      return;
  } else if(!fmt) return;    

/* we need to use a back end function to get the buffer because the
   cfm glue can't be rooting around in the internal structs */
  _sasl_get_errorbuf(conn, &error_buf, &error_buf_len);

  formatlen = strlen(fmt);

  va_start(ap, fmt); /* start varargs */

  while(pos<formatlen)
  {
    if (fmt[pos]!='%') /* regular character */
    {
      result = _buf_alloc(error_buf, error_buf_len, outlen+1);
      if (result != SASL_OK)
    return;
      (*error_buf)[outlen]=fmt[pos];
      outlen++;
      pos++;
    } else { /* formating thing */
      int done=0;
      char frmt[10];
      int frmtpos=1;
      char tempbuf[21];
      frmt[0]='%';
      pos++;

      while (done==0)
      {
    switch(fmt[pos])
      {
      case 's': /* need to handle this */
        cval = va_arg(ap, char *); /* get the next arg */
        result = _sasl_add_string(error_buf, error_buf_len,
                      &outlen, cval);

        if (result != SASL_OK) /* add the string */
          return;

        done=1;
        break;

      case '%': /* double % output the '%' character */
        result = _buf_alloc(error_buf, error_buf_len, outlen+1);
        if (result != SASL_OK)
          return;
        (*error_buf)[outlen]='%';
        outlen++;
        done=1;
        break;

      case 'm': /* insert the errno string */
        result = _sasl_add_string(error_buf, error_buf_len,
                      &outlen,
                      strerror(va_arg(ap, int)));
        if (result != SASL_OK)
          return;
        done=1;
        break;

      case 'z': /* insert the sasl error string */
        result = _sasl_add_string(error_buf, error_buf_len, &outlen,
             (char *)sasl_errstring(_sasl_seterror_usererr(
                            va_arg(ap, int)),NULL,NULL));
        if (result != SASL_OK)
          return;
        done=1;
        break;

      case 'c':
        frmt[frmtpos++]=fmt[pos];
        frmt[frmtpos]=0;
        tempbuf[0] = (char) va_arg(ap, int); /* get the next arg */
        tempbuf[1]='\0';

        /* now add the character */
        result = _sasl_add_string(error_buf, error_buf_len,
                      &outlen, tempbuf);
        if (result != SASL_OK)
          return;
        done=1;
        break;

      case 'd':
      case 'i':
        frmt[frmtpos++]=fmt[pos];
        frmt[frmtpos]=0;
        ival = va_arg(ap, int); /* get the next arg */

        snprintf(tempbuf,20,frmt,ival); /* have snprintf do the work */
        /* now add the string */
        result = _sasl_add_string(error_buf, error_buf_len,
                      &outlen, tempbuf);
        if (result != SASL_OK)
          return;
        done=1;

        break;
      default: 
        frmt[frmtpos++]=fmt[pos]; /* add to the formating */
        frmt[frmtpos]=0;        
        if (frmtpos>9) 
          done=1;
      }
    pos++;
    if (pos>formatlen)
      done=1;
      }

    }
  }

  (*error_buf)[outlen]='\0'; /* put 0 at end */

  va_end(ap);  

#ifndef SASL_OSX_CFMGLUE
  if(!(flags & SASL_NOLOG)) {
      /* See if we have a logging callback... */
      result = _sasl_getcallback(conn, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx);
      if (result == SASL_OK && ! log_cb)
      result = SASL_FAIL;
      if (result != SASL_OK)
      return;

      result = log_cb(log_ctx, SASL_LOG_FAIL, conn->error_buf);
  }
#endif /* SASL_OSX_CFMGLUE */
}

それらの周りに#defineはまったくありません。私がコンパイルすると:gcc -DHAVE_CONFIG_H -I. -I.. -I../include -I../lib -I../sasldb -I../include -Wall -W -g -O2 -c seterror.cnmは以下を生成します:

$ nm seterror.o
00000000 b .bss
00000000 d .data
00000000 N .debug_abbrev
00000000 N .debug_aranges
00000000 N .debug_info
00000000 N .debug_line
00000000 N .debug_loc
00000000 N .debug_ranges
00000000 N .debug_str
00000000 r .eh_frame
00000000 r .rdata
00000000 t .text
         U __buf_alloc
         U __imp__sasl_errstring
         U __sasl_add_string
         U __sasl_get_errorbuf
         U __sasl_getcallback
00000000 T _sasl_seterror
         U _snprintf
         U _strerror

なぜ住所がないのですか?ライブラリでnmを実行すると、次のようになります。

$ nm .libs / libsasl2.a | grep sasl_seterror
         U __imp__sasl_seterror
         U __imp__sasl_seterror
         U __imp__sasl_seterror
         U __imp__sasl_seterror
         U __imp__sasl_seterror
         U __imp__sasl_seterror
         U __imp__sasl_seterror
00000000 T _sasl_seterror

まだ住所がないのはなぜですか?最後に、ライブラリに対してリンクしようとすると、「。」というエラーが表示されますundefined reference to '__imp__sasl_seterror'

誰かがここで何が起こっているのか説明するのを手伝ってもらえますか?

4

2 に答える 2

2
static int _sasl_seterror_usererr(int saslerr);

void sasl_seterror(sasl_conn_t *conn,
           unsigned flags,
           const char *fmt, ...);

どちらも関数を定義せず、宣言するだけです。彼らはあなたがその機能を提供することを約束しますが、それ自体は提供しません。その結果、約束を破るとリンクエラーが発生します。

アドレスを取得してそれにリンクするには、実際に関数を定義する必要があります。

于 2012-08-13T17:38:58.917 に答える
0

次のようにリンクされたヘッダー行がありました。

LIBSASL_API void sasl_seterror(sasl_conn_t *conn, unsigned flags,
                   const char *fmt, ...);

そして、LIBSASL_API次のように定義されました。


#ifdef WIN32
#  ifdef LIBSASL_EXPORTS
#   define LIBSASL_API  __declspec(dllexport)
#  else /* LIBSASL_EXPORTS */
#   define LIBSASL_API  __declspec(dllimport)
#  endif /* LIBSASL_EXPORTS */
#else /* WIN32 */
# define LIBSASL_API extern
#endif /* WIN32 */

したがって、関数は動的にリンクされるかのようにコンパイルされていました。

ただし、nm はまだ sasl_seterror に対して 00000000 T を生成していますが、リンカはその機能について文句を言っていません。

于 2012-08-13T18:42:18.447 に答える