Skip to content

Instantly share code, notes, and snippets.

@ryankask
Created June 7, 2013 08:22
Show Gist options
  • Save ryankask/5727814 to your computer and use it in GitHub Desktop.
Save ryankask/5727814 to your computer and use it in GitHub Desktop.
Sample C extension module in Python. Fetches a URL using libcurl.
#include <Python.h>
#include <curl/curl.h>
typedef struct Bucket {
char *contents;
size_t size;
} Bucket;
static PyObject *CurlyError;
static size_t fill_bucket_callback(void *contents, size_t size, size_t nmemb,
void *userdata)
{
size_t total_size = size * nmemb;
Bucket *bucket = (Bucket *)userdata;
bucket->contents = realloc(bucket->contents, bucket->size + total_size + 1);
if (bucket->contents == NULL) {
return 0;
}
memcpy(&(bucket->contents[bucket->size]), contents, total_size);
bucket->size += total_size;
bucket->contents[bucket->size] = 0;
return total_size;
}
static char *fetch(const char *url)
{
CURL *curl;
CURLcode res;
Bucket bucket;
bucket.contents = malloc(0);
bucket.size = 0;
if (bucket.contents == NULL) {
return NULL;
}
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fill_bucket_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&bucket);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
PyErr_SetString(CurlyError, curl_easy_strerror(res));
return NULL;
}
curl_easy_cleanup(curl);
}
return bucket.contents;
}
/* Python interface */
static PyObject *curly_fetch(PyObject *self, PyObject *args)
{
const char *url, *body;
if (!PyArg_ParseTuple(args, "s", &url)) {
return NULL;
}
body = fetch(url);
if (body == NULL) {
return NULL;
}
return PyUnicode_FromString(body);
}
static PyMethodDef CurlyMethods[] = {
{"fetch", curly_fetch, METH_VARARGS, "Fetch the body of a webpage."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initcurly(void)
{
PyObject *module = Py_InitModule("curly", CurlyMethods);
if (module == NULL) {
return;
}
CurlyError = PyErr_NewException("curly.CurlyError", NULL, NULL);
Py_INCREF(CurlyError);
PyModule_AddObject(module, "CurlyError", CurlyError);
}
from distutils.core import setup, Extension
curly = Extension('curly',
libraries=['curl'],
sources=['curly.c'])
setup(name='Curly',
version='0.1.1',
author='Ryan Kaskel',
author_email='dev@ryankaskel.com',
ext_modules=[curly])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment