简体   繁体   中英

Import error in Python for libcurl library

I have written a program in c using libcurl to load url and send the return value to Python (I am passing 2 integer value from Python to C. i am yet to enhance the code, currently trying the logic and variable accessibility between Python and C.). I am able to compile the program successfully. When i load the module in Python i am getting error saying "undefined symbol: curl_easy_getinfo". Please let me know how to fix the issue.

Code:

#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
>>>

Try moving -lcurl and -lpthread to after sample.c in your compilation command. The linker resolves symbols in left-to-right order, so references from sample.c (eg, curl_easy_getinfo ) will be resolved from libraries specified after it.

It's better to use -pthread than -lpthread by the way. It sets preprocessor flags to make some functions reentrant for example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM