在Python中为libcurl库导入错误

2024-06-10 03:45:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我用c语言编写了一个程序,使用libcurl加载url并将返回值发送给Python(我正在从Python向c传递2个整数值。我还没有增强代码,目前正在尝试Python和c之间的逻辑和变量可访问性)。我能成功地编译程序。当我在Python中加载模块时,我得到一个错误消息:“undefined symbol:curl_easy_getinfo”。请告诉我如何解决这个问题。在

代码:

#include <Python.h>
#include <stdio.h>
#include <time.h>
#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h>

#define NUMT 4

/*
  List of URLs to fetch.

  If you intend to use a SSL-based protocol here you MUST setup the OpenSSL
  callback functions as described here:

  http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION

*/

const char * const urls[NUMT]= {
  "http://www.google.com",
  "http://www.yahoo.com/",
  "http://www.haxx.se/done.html",
  "http://www.haxx.se/"
};

#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL     3

struct myprogress {
  double lastruntime;
  curl_off_t totdnld;
  void *url;
  CURL *curl;
};

static PyObject *foo1_add(PyObject *self, PyObject *args)
{
    int a;
    int b;
    int s;

    if (!PyArg_ParseTuple(args, "ii", &a, &b))
    {
        return NULL;
    }

    s = sum (a, b);
    return Py_BuildValue("i", s);
   // return Py_BuildValue("i", a + b);
}

static PyMethodDef foo1_methods[] = {
    { "add", (PyCFunction)foo1_add, METH_VARARGS, NULL },
    { NULL, NULL, 0, NULL }
};

PyMODINIT_FUNC initfoo1()
{
    Py_InitModule3("foo1", foo1_methods, "My first extension module.");
}

int sum(int x, int y) {
   int z;

   z = x + y;
   z = geturl (x, y);
   return (z);
}

/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
#ifdef 0
static int xferinfo(void *p,
                    curl_off_t dltotal, curl_off_t dlnow,
                    curl_off_t ultotal, curl_off_t ulnow)
{
  struct myprogress *myp = (struct myprogress *)p;
  CURL *curl = myp->curl;
  double curtime = 0;

  curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);

  /* under certain circumstances it may be desirable for certain functionality
     to only run every N seconds, in order to do this the transaction time can
     be used */
  if((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) {
    myp->lastruntime = curtime;
    fprintf(stderr, "TOTAL TIME: %f \r\n", curtime);
  }

  if (dlnow > 0) {
  fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
          "  DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
          "\r\n",
          ulnow, ultotal, dlnow, dltotal);
  }

  myp->totdnld = myp->totdnld + dlnow;

  if (dlnow > 0) {
  fprintf(stderr, "TOTAL Download: %" CURL_FORMAT_CURL_OFF_T " url is: %s \r\n", myp->totdnld, myp->url);
  }

 // if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES)
  //  return 1;
  return 0;
}
#endif
/* for libcurl older than 7.32.0 (CURLOPT_PROGRESSFUNCTION) */
static int older_progress(void *p,
                          double dltotal, double dlnow,
                          double ultotal, double ulnow)
{
  return xferinfo(p,
                  (curl_off_t)dltotal,
                  (curl_off_t)dlnow,
                  (curl_off_t)ultotal,
                  (curl_off_t)ulnow);
}

static void *pull_one_url(void *url)
{
  CURL *curl;
  CURLcode res = CURLE_OK;
  struct myprogress prog;

  curl = curl_easy_init();
  if(curl) {
    prog.lastruntime = 0;
    prog.curl = curl;
    prog.url = url;
    prog.totdnld = (curl_off_t) 0;
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, older_progress);
    /* pass the struct pointer into the progress function */
    curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog);
#ifdef 0
#if LIBCURL_VERSION_NUM >= 0x072000
    /* xferinfo was introduced in 7.32.0, no earlier libcurl versions will
       compile as they won't have the symbols around.

       If built with a newer libcurl, but running with an older libcurl:
       curl_easy_setopt() will fail in run-time trying to set the new
       callback, making the older callback get used.

       New libcurls will prefer the new callback and instead use that one even
       if both callbacks are set. */

    curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
    /* pass the struct pointer into the xferinfo function, note that this is
       an alias to CURLOPT_PROGRESSDATA */
    curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);
#endif
#endif
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
    res = curl_easy_perform(curl);
    if(res != CURLE_OK)
      fprintf(stderr, "%s\n", curl_easy_strerror(res));
    curl_easy_cleanup(curl);

  }
  return NULL;
}


/*
   int pthread_create(pthread_t *new_thread_ID,
   const pthread_attr_t *attr,
   void * (*start_func)(void *), void *arg);
*/

int geturl(int x, int y)
{
  pthread_t tid[NUMT];
  int i;
  int error;

  /* Must initialize libcurl before any threads are started */
  curl_global_init(CURL_GLOBAL_ALL);

  for(i=0; i< NUMT; i++) {
    error = pthread_create(&tid[i],
                           NULL, /* default attributes please */
                           pull_one_url,
                           (void *)urls[i]);
    if(0 != error)
      fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
    else
      fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
  }

  /* now wait for all threads to terminate */
  for(i=0; i< NUMT; i++) {
    error = pthread_join(tid[i], NULL);
    fprintf(stderr, "Thread %d terminated\n", i);
  }

  return (x * y);
}

Command used for compilation:
gcc -lcurl -lpthread -shared -I/usr/include/python2.7  -fPIC sample.c –o add.so

Error:
>>> import foo1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: ./foo1.so: undefined symbol: curl_easy_perform
>>>

Tags: theurlreturnifincludeeasycurlnull
1条回答
网友
1楼 · 发布于 2024-06-10 03:45:28

尝试在编译命令中将-lcurl和{}移到sample.c之后。链接器按从左到右的顺序解析符号,因此来自sample.c(例如,curl_easy_getinfo)的引用将从其后指定的库中解析。在

顺便说一下,使用-pthread比使用-lpthread要好。例如,它设置预处理器标志以使某些函数可重入。在

相关问题 更多 >