Python-BlogServer博客-C调用Python的wsgi接口

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Python Web Server Gateway Interface

python的wsgi接口,调用这个接口的主要原因在于要使用python作为动态网站的后端语言(c语言作为后端编写起来还是很慢的,除非是静态网站,静态网站纯c服务器也许会在后面继续研究),socket连接采用前一章写的c程序

python的wsgi接口参考:https://www.python.org/dev/peps/pep-3333/

python的c api接口参考:https://docs.python.org/2.7/c-api/

有了上面资料就开始这一章的编程了

首先后端采用python的django框架

django官网:https://www.djangoproject.com/

对于python使用pip安装即可,这里使用的是最新的1.8.4

from mysite import wsgi

def start_response(status, response_headers, exc_info=None):
    print status

def HttpServer(method,path,req):
    environ = {'REQUEST_METHOD':method,'SERVER_NAME':'BlogServer','QUERY_STRING':req,'SERVER_PORT':'80','PATH_INFO':path,'wsgi.input':''}
    return wsgi.application(environ,start_response)

print HttpServer('GET','/admin/1/2','')#为了方便我们仅仅提取出三个接口,对于get方法,只有与请求链接与查询字符串两部分

这个文件保存在顶层mysite目录下,而不是mysite/mysite/目录下

由于我们请求一个不存在的链接所以会返回404状态码以及响应头和html正文

Python-BlogServer博客-C调用Python的wsgi接口_第1张图片

 

修改请求/admin/

Python-BlogServer博客-C调用Python的wsgi接口_第2张图片

302重定向

再修改成HttpServer('GET','/admin/login/','next=/admin/')

Python-BlogServer博客-C调用Python的wsgi接口_第3张图片

这次就是200正常响应了

根据上面python的wsgi接口的调用我们也知道该如果使用该接口,接下来就是用c语言来调用这个接口了

对于c调用python这部分内容在国内的网站极少描述,啃了好久官方的英文文档

#include
#include

static PyObject *start_response(PyObject *self, PyObject *args)//相当于上面python里面的start_response
{
    printf("%s\n",PyString_AsString(PyObject_Str(PyTuple_GetItem(args, 0))));
    printf("%s\n",PyString_AsString(PyObject_Str(PyTuple_GetItem(args, 1))));
    return Py_None;
}

static struct PyMethodDef start_response_methods[] = {

//构建module使用,可能我还能吭透官方文档,所不能有直接回调的PyObject *构建方法
    {"start_response", start_response, METH_VARARGS},
    {NULL, NULL}};

int main()
{
    Py_Initialize();//初始化
    if (!Py_IsInitialized()) return -1;//是否正确初始化
    PyRun_SimpleString("import sys");//导入sys
    PyRun_SimpleString("sys.path.append('./')");//设置当前目录为工作目录
    PyObject *pModule = PyImport_ImportModule("mysite.wsgi");//导入wsgi接口
    if(!pModule){
            printf("import failed!\n");//导入失败提示
            return -1;
        }
    PyObject *pFunc = PyObject_GetAttrString(pModule, "application");//导入wsgi的调用
    if(!pFunc){
               printf("get function failed!\n");//失败提示
               return -1;
        }
    PyObject *environ = PyDict_New();//构建python的字典类型
    PyDict_SetItemString(environ, "REQUEST_METHOD", PyString_FromString("GET"));
    PyDict_SetItemString(environ, "SERVER_NAME", PyString_FromString("BlogServer"));
    PyDict_SetItemString(environ, "SERVER_PORT", PyString_FromString("80"));
    PyDict_SetItemString(environ, "QUERY_STRING", PyString_FromString(""));
    PyDict_SetItemString(environ, "PATH_INFO", PyString_FromString("/"));
    PyDict_SetItemString(environ, "wsgi.input", PyString_FromString(""));

    PyObject *module = Py_InitModule("start_response", start_response_methods);
    PyObject *response = PyObject_GetAttrString(module, "start_response");//还要从module里获取回需要的回调方法(也许有更好的办法)

    PyObject *pArgs = PyTuple_New(2);//构建元组类型,传参使用

    PyTuple_SetItem(pArgs, 0, environ);
    PyTuple_SetItem(pArgs, 1, response);
    PyObject *res = PyObject_CallObject(pFunc, pArgs);
    printf("%s",PyString_AsString(PyObject_Str(res)));//打印结果

    //把指针都回收销毁掉

    Py_DECREF(res);
    Py_DECREF(pArgs);
    Py_DECREF(response);
    Py_DECREF(environ);
    Py_DECREF(pModule);
    Py_DECREF(pFunc);
    Py_Finalize();
    Py_DECREF(module);


    return 0;
}

python2.7编译一下

gcc cpy.c  -o cpy -lpython2.7
Python-BlogServer博客-C调用Python的wsgi接口_第4张图片

编译运行一下

PyObject其实就是python中的变量名,却没有固定的一个数据类型,在c语言中也是这么体现的,感觉有点特别,等下一部分将会合并前面多线程socket编程,构成一个正常的服务器

转载于:https://my.oschina.net/tmj1993/blog/500171

你可能感兴趣的:(Python-BlogServer博客-C调用Python的wsgi接口)