Welcome, guest | Sign In | My Account | Store | Cart

Add function to __builtin__ module through C API

Sometimes it need to embedding a Python script to a C code, and it references to a function, which also provided by the same C code. Then you have to import the module, as you defined in your C code.

But this import would be skipped, if you add your function to your __builtin__ module. In Python3 (3.5), there is the PyModule_AddFunctions() function, but in the previous versions, you can make it like this snippet.

See these recipes:

Makefile: https://code.activestate.com/recipes/579111-add-function-to-__builtin__-module-through-c-api-c/

Python script: https://code.activestate.com/recipes/579112-add-function-to-__builtin__-module-through-c-api-c/

C, 141 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <stdio.h>
#include <Python.h>

PyObject *pName, *pModule, *pFunc;
PyObject *builtin,  *builtinname, *builtin_dict, *myfunc;

/* python mymodule */
static PyObject*
mymodule_usleep(PyObject *self, PyObject *args)
{
    unsigned long  i;

    if (!PyArg_ParseTuple(args, "k:usleep", &i)) {
	return NULL;
    }
    usleep(i);

    return Py_None;
}

static char mymodule_usleep_doc[] =
    "usleep(unsigned long) - Sleep for the specified number of microseconds.";

static PyMethodDef mymodule_methods[] = {
    {"usleep",	mymodule_usleep,	METH_VARARGS,	mymodule_usleep_doc},
    {NULL, NULL}
};
/* python mymodule */

int
pyinit(char * pfile)
{
    char syspath[255], pwd[255];
    char fname[] = "bar";

    Py_Initialize();

    /* need for add pwd directory */
    PyRun_SimpleString("import sys");
    strcpy(syspath, "sys.path.append('");
        if (getcwd(pwd, sizeof(pwd)) != NULL) {
            strcat(syspath, pwd);
        }
    strcat(syspath, "')");

    PyRun_SimpleString(syspath);

    /* add new function to __builtin__ module  */
    // http://stackoverflow.com/questions/6565175/adding-new-command-to-module-through-c-api
    // Python3: https://mail.python.org/pipermail/python-list/2015-October/697917.html
    pName = PyString_FromString("__builtin__");
    builtin = PyImport_Import(pName);
    builtinname = PyString_FromString("__builtin__");
    
    builtin_dict = PyModule_GetDict(builtin);
    myfunc = PyCFunction_NewEx(&mymodule_methods[0], (PyObject*)NULL, builtinname);
    PyDict_SetItemString(builtin_dict, "usleep", myfunc);
    
    Py_DECREF(pName);
    /* end of new function adding */

    /* load Own python script */
    pName = PyString_FromString(pfile);
    PyErr_Print();

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, fname);

        if (pFunc && PyCallable_Check(pFunc)) {
	    return 0;
        }
        else {
            if (PyErr_Occurred()) {
                PyErr_Print();
	    }
            fprintf(stderr, "Cannot find function \"%s\"\n", fname);
	    Py_XDECREF(pFunc);
	    Py_XDECREF(pModule);
	    Py_XDECREF(builtin);
	    Py_XDECREF(builtinname);
	    Py_XDECREF(builtin_dict);
	    Py_XDECREF(myfunc);
	    return 1;
        }
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", pfile);
        return 1;
    }
    return 0;
}

void myloop() {
    int rc, var1, var2;
    PyObject *mydict, *pArgs, *pValue;

    printf("Enter numbers:");
    rc = scanf("%d %d", &var1, &var2);
    while (rc == 2) {
	mydict = Py_BuildValue("{sisi}","a", var1, "b", var2);
	pArgs = PyTuple_New(1);
	PyTuple_SetItem(pArgs, 0, mydict);

	pValue = PyObject_CallObject(pFunc, pArgs);
	Py_DECREF(pArgs);
	if (pValue != NULL) {
	    printf("Result of call: %ld\n", PyInt_AsLong(pValue));
	    Py_DECREF(pValue);
	}
	else {
	    PyErr_Print();
	    fprintf(stderr,"Call failed\n");
	}
	Py_DECREF(mydict);
	printf("Enter numbers: ");
	rc = scanf("%d %d", &var1, &var2);
    }
}

int main(int argc, char **argv) {
    if (argc < 2) {
	fprintf(stderr, "Usage: call pythonfile\n");
	return 1;
    }
    if (pyinit(argv[1]) == 0) {
	myloop();
	Py_DECREF(pFunc);
	Py_DECREF(pModule);
	Py_DECREF(builtin);
	Py_DECREF(builtinname);
	Py_DECREF(builtin_dict);
	Py_DECREF(myfunc);
    }

    Py_Finalize();
    return 0;
}
Created by airween on Thu, 15 Oct 2015 (GPL3)
C recipes (32)
airween's recipes (3)

Required Modules

Other Information and Tasks