Article Index

Extending & Embedding Python Using C

extendPython360

We have decided not to make the programs available as a download because this is not the point of the book - the programs are not finished production code but something you should type in and study.

The best solution is to provide the source code of the programs in a form that can be copied and pasted into an editor. 

The only downside is that you have to create a project to paste the code into.

To do this follow the instructions in the book.

Notice that indents have been removed but you can put them back in by auto formatting the code after pasting.

All of the programs below were copy and pasted from working programs in the IDE. They have been formatted using the built in formatter and hence are not identical in layout to the programs in the book.

This is to make copy and pasting them easier. The programs in the book are formatted to be easy to read on the page.

If anything you consider important is missing or if you have any requests or comments  contact:

This email address is being protected from spambots. You need JavaScript enabled to view it. 


Page 23

Hello.c

#include
int main(int argc, char **argv)
{
printf("Hello C World\n");
return 0;
}

tasks.json

{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/gcc",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

launch.json

{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "enter program name, for example ${workspaceFolder}/a.out",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}

 

 

Page 24

arith.c

#define PY_SSIZE_T_CLEAN
#include

static PyObject *add(PyObject *self, PyObject *args)
{
int x, y, sts;
if (!PyArg_ParseTuple(args, "ii", &x, &y))
return NULL;
sts = x + y;
return PyLong_FromLong(sts);
}

static PyMethodDef AddMethods[] = {
{"add", add, METH_VARARGS, "add two numbers"},
{NULL, NULL, 0, NULL} // sentinel
};

static struct PyModuleDef addmodule = {
PyModuleDef_HEAD_INIT,
"arith",
"C library for sum",
-1,
AddMethods};

PyMODINIT_FUNC PyInit_arith(void)
{
return PyModule_Create(&addmodule);
}

tasks.json

{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc-10 build active file",
"command": "/usr/bin/gcc-10",
"args": [
"-fdiagnostics-color=always",
"-g",
"-shared",
"${file}",
"-o",
"arith.so",
"-I/usr/local/include/python3.11"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

c_cpp_properties.json

{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/usr/local/include/**"
],

"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-arm"
}
],
"version": 4
}

test.py

import arith
print(arith.add(1,2))
print(dir(arith))

Page 30

launch.json

{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "(gdb) Attach",
"type": "cppdbg",
"request": "attach",
"program": "/usr/local/bin/python3.11",
"processId": "${command:pickProcess}",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

 


Page 38

 hello.c

#include <stdio.h>

int main(int argc, char **argv)

{

    printf("Hello C World\n");

    return 0;

}

 tasks.json

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: cl.exe build active file",

            "command": "cl.exe",

            "args": [

                "/Zi",

                "/EHsc",

                "/nologo",

                "/Fe${fileDirname}\\${fileBasenameNoExtension}.exe",

                "${file}"

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$msCompile"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

Page 30

Change mike.james in the quoted paths to your own user name

arith.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *add(PyObject *self, PyObject *args)

{

    int x, y, sts;

    if (!PyArg_ParseTuple(args, "ii", &x, &y))

        return NULL;

    sts = x + y;

    return PyLong_FromLong(sts);

}

static PyMethodDef AddMethods[] = {

    {"add", add, METH_VARARGS, "add two numbers"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "arith",

    "C library for sum",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_arith(void)

{

    return PyModule_Create(&addmodule);

}

tasks.json

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: cl.exe build active file",

            "command": "cl.exe",

            "args": [

                "/Zi",

                "/EHsc",

                "/nologo",            

                "/IC:/Users/mike.james/AppData/Local/Programs/Python/Python311/include",              

                "${file}",

                "/link /dll /OUT:arith.pyd /LIBPATH:C:/Users/mike.james/AppData/Local/Programs/Python/Python311/libs"

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$msCompile"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

 launch.json

{

    "version": "0.2.0",

    "configurations": [

        {

            "name": "(Windows) Attach",

            "type": "cppvsdbg",

            "request": "attach",

            "processId": "${command:pickProcess}",

            "symbolSearchPath": "C:/Users/mike.james/AppData/Local/Programs/Python/Python-3.11.4",

            "sourceFileMap":{"D:/a/1/s/":"C:/Users/mike.james/AppData/Local/Programs/Python/Python311"},

        },

        {

            "name": "Python: Current File",

            "type": "python",

            "request": "launch",

            "program": "${file}",

            "console": "integratedTerminal"

        }

    ]

}

c_cpp_properties.json

{

    "configurations": [

        {

            "name": "Win32",

            "includePath": [

                "${workspaceFolder}/**",

                "C:/Users/mike.james/AppData/Local/Programs/Python/Python311/include/"

            ],

            "defines": [

                "_DEBUG",

                "UNICODE",

                "_UNICODE"

            ],

            "windowsSdkVersion": "10.0.22000.0",

            "compilerPath": "cl.exe",

            "cStandard": "c17",

            "cppStandard": "c++17",

            "intelliSenseMode": "windows-msvc-x64"

        }

    ],

    "version": 4

}

test.py

import arith

print(arith.add(1,2))

print(dir(arith))

 

 Page 44

launch.json

{

    "version": "0.2.0",

    "configurations": [

        {

            "name": "(Windows) Attach",

            "type": "cppvsdbg",

            "request": "attach",

            "processId": "${command:pickProcess}",

        },

        {

            "name": "Python: Current File",

            "type": "python",

            "request": "launch",

            "program": "${file}",

            "console": "integratedTerminal"

        }

    ]

}


 

 

Page 53

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject * add(PyObject *self, PyObject *args)

{

    int x, y, sts;

    if (!PyArg_ParseTuple(args, "ii", &x, &y))

        return NULL;

    sts = x+y;

    return PyLong_FromLong(sts);

}

static PyMethodDef AddMethods[] = {

    {"add", add, METH_VARARGS, "add two numbers"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

  PyModuleDef_HEAD_INIT,

  "arith",                              

  "C library for sum",  

  -1,                                  

  AddMethods                          

};

PyMODINIT_FUNC PyInit_arith(void) {    

     return PyModule_Create(&addmodule);

}

Page 54 and on

Arith.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject * Pi(PyObject *self, PyObject *args)

{

    int m, n;

    double pi,s;

    if (!PyArg_ParseTuple(args, "ii", &m, &n))

        return NULL;

    pi=0;

    for(int k=m;k<n;k++){

        s=1;

        if(k%2==0)s=-1;

        pi=pi+s/(2*k-1);

    }    

    return PyFloat_FromDouble(4*pi);

}

static PyMethodDef AddMethods[] = {

    {"myPi", Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

  PyModuleDef_HEAD_INIT,

  "Pi",                              

  "C library to compute Pi",  

  -1,                                  

  AddMethods                          

};

PyMODINIT_FUNC PyInit_Pi(void) {    

     return PyModule_Create(&addmodule);

}

tasks.json   LINUX

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: gcc-10 build active file",

            "command": "/usr/bin/gcc-10",

            "args": [

                "-fdiagnostics-color=always",

                "-g",

                "-shared",

                "${file}",

                "-o",

                "Pi.so",

                "-I/usr/local/include/python3.11"  

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$gcc"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

c_cpp_properties.json LINUX

{

    "configurations": [

        {

            "name": "Linux",

            "includePath": [

                "${workspaceFolder}/**",

                "/usr/local/include/**"

            ],

            "defines": [],

            "compilerPath": "/usr/bin/gcc",

            "cStandard": "c17",

            "cppStandard": "gnu++14",

            "intelliSenseMode": "linux-gcc-arm"

        }

    ],

    "version": 4

}

launch.json LINUX

{

    "version": "0.2.0",

    "configurations": [

      {

          "name": "Python: Current File",

          "type": "python",

          "request": "launch",

          "program": "${file}",

          "console": "integratedTerminal"

      },

      {

          "name": "(gdb) Attach",

          "type": "cppdbg",

          "request": "attach",

          "program": "/usr/local/bin/python3.11",

          "processId": "${command:pickProcess}",

          "MIMode": "gdb",

          "setupCommands": [

              {

                  "description": "Enable pretty-printing for gdb",

                  "text": "-enable-pretty-printing",

                  "ignoreFailures": true

              }

          ]

      }

    ]

  }

tasks.json   WINDOWS - CHANGE USER IN PATH

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: cl.exe build active file",

            "command": "cl.exe",

            "args": [

                "/Zi",

                "/EHsc",

                "/nologo",            

                "/IC:/Users/mike.james/AppData/Local/Programs/Python/Python311/include",              

                "${file}",

                "/link /dll /OUT:arith.pyd /LIBPATH:C:/Users/mike.james/AppData/Local/Programs/Python/Python311/libs"

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$msCompile"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

 c_cpp_properties.json WINDOWS CHANGE USER IN PATH

{

    "configurations": [

        {

            "name": "Win32",

            "includePath": [

                "${workspaceFolder}/**",

                "C:/Users/mike.james/AppData/Local/Programs/Python/Python311/include/"

            ],

            "defines": [

                "_DEBUG",

                "UNICODE",

                "_UNICODE"

            ],

            "windowsSdkVersion": "10.0.22000.0",

            "compilerPath": "cl.exe",

            "cStandard": "c17",

            "cppStandard": "c++17",

            "intelliSenseMode": "windows-msvc-x64"

        }

    ],

    "version": 4

}

launch.json WINDOWS CHANGE USER IN PATH 

{

    "version": "0.2.0",

    "configurations": [

        {

            "name": "(Windows) Attach",

            "type": "cppvsdbg",

            "request": "attach",

            "processId": "${command:pickProcess}",

            "symbolSearchPath": "C:/Users/mike.james/AppData/Local/Programs/Python/Python-3.11.4",

            "sourceFileMap":{"D:/a/1/s/":"C:/Users/mike.james/AppData/Local/Programs/Python/Python311"},

        },

        {

            "name": "Python: Current File",

            "type": "python",

            "request": "launch",

            "program": "${file}",

            "console": "integratedTerminal"

        }

    ]

}

Py.py

import time

def myPi(m,n):

    pi=0

    for k in range(m,n+1):

        s= 1 if k%2 else -1

        pi += s / (2 * k - 1)

    return 4*pi

if __name__ == '__main__':

    N=10000000

    t1=time.perf_counter()

    pi=myPi(1,N)

    t2=time.perf_counter()

    print((t2-t1)*1000)

    print(pi)

Py1.py

import Pi

import time

if __name__ == '__main__':

    N=10000000

    t1=time.perf_counter()

    pi=Pi.myPi(1,N)

    t2=time.perf_counter()

    print((t2-t1)*1000)

    print(pi)

Page 57

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject* exampleFunction(PyObject *self, PyObject *args)

{  

     //example function code

}

static PyMethodDef AddMethods[] = {

    {"exampleFunction", exampleFunction, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

  PyModuleDef_HEAD_INIT,

  "example",                              

  "C library to test API",  

  -1,                                  

  AddMethods                          

};

PyMODINIT_FUNC PyInit_example(void) {    

     return PyModule_Create(&addmodule);

}

tasks.json LINUX

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: gcc-10 build active file",

            "command": "/usr/bin/gcc-10",

            "args": [

                "-fdiagnostics-color=always",

                "-g",

                "-shared",

                "${file}",

                "-o",

                "example.so",

                "-I/usr/local/include/python3.11"  

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$gcc"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

launch.json LINUX

{

    "version": "0.2.0",

    "configurations": [

      {

          "name": "Python: Current File",

          "type": "python",

          "request": "launch",

          "program": "${file}",

          "console": "integratedTerminal"

      },

      {

          "name": "(gdb) Attach",

          "type": "cppdbg",

          "request": "attach",

          "program": "/usr/local/bin/python3.11",

          "processId": "${command:pickProcess}",

          "MIMode": "gdb",

          "setupCommands": [

              {

                  "description": "Enable pretty-printing for gdb",

                  "text": "-enable-pretty-printing",

                  "ignoreFailures": true

              }

          ]

      }

    ]

  }

c_cpp_properties.json LINUX

{

    "configurations": [

        {

            "name": "Linux",

            "includePath": [

                "${workspaceFolder}/**",

                "/usr/local/include/**"

            ],

            "defines": [],

            "compilerPath": "/usr/bin/gcc",

            "cStandard": "c17",

            "cppStandard": "gnu++14",

            "intelliSenseMode": "linux-gcc-arm"

        }

    ],

    "version": 4

}

tasks.json   WINDOWS - CHANGE USER IN PATH

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: cl.exe build active file",

            "command": "cl.exe",

            "args": [

                "/Zi",

                "/EHsc",

                "/nologo",            

                "/IC:/Users/mike.james/AppData/Local/Programs/Python/Python311/include",              

                "${file}",

                "/link /dll /OUT:example.pyd /LIBPATH:C:/Users/mike.james/AppData/Local/Programs/Python/Python311/libs"

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$msCompile"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

 

 c_cpp_properties.json WINDOWS CHANGE USER IN PATH

{

    "configurations": [

        {

            "name": "Win32",

            "includePath": [

                "${workspaceFolder}/**",

                "C:/Users/mike.james/AppData/Local/Programs/Python/Python311/include/"

            ],

            "defines": [

                "_DEBUG",

                "UNICODE",

                "_UNICODE"

            ],

            "windowsSdkVersion": "10.0.22000.0",

            "compilerPath": "cl.exe",

            "cStandard": "c17",

            "cppStandard": "c++17",

            "intelliSenseMode": "windows-msvc-x64"

        }

    ],

    "version": 4

}

 

launch.json WINDOWS CHANGE USER IN PATH 

{

    "version": "0.2.0",

    "configurations": [

        {

            "name": "(Windows) Attach",

            "type": "cppvsdbg",

            "request": "attach",

            "processId": "${command:pickProcess}",

            "symbolSearchPath": "C:/Users/mike.james/AppData/Local/Programs/Python/Python-3.11.4",

            "sourceFileMap":{"D:/a/1/s/":"C:/Users/mike.james/AppData/Local/Programs/Python/Python311"},

        },

        {

            "name": "Python: Current File",

            "type": "python",

            "request": "launch",

            "program": "${file}",

            "console": "integratedTerminal"

        }

    ]

}

 


 

Page 72

example.c

This is the combined code from the chapter - the json files are as for example given ealier

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *stringRaw(PyObject *self, PyObject *args)

{

     char *name;

     if (!PyArg_ParseTuple(args, "s", &name))

          return NULL;

     printf("%s\n", name);

     for (int i = 0; name[i]; i++)

     {

          printf("%02X ", (unsigned char)name[i]);

     }

     printf("\n");

     Py_RETURN_NONE;

}

static PyObject *stringRawLen(PyObject *self, PyObject *args)

{

     char *name;

     Py_ssize_t len;

     if (!PyArg_ParseTuple(args, "s#", &name, &len))

          return NULL;

     printf("%s\n", name);

     printf("%d\n", (int)len);

     for (int i = 0; i < len; i++)

     {

          printf("%02X ", (unsigned char)name[i]);

     }

     printf("\n");

     Py_RETURN_NONE;

}

static PyObject *stringPBuffer(PyObject *self, PyObject *args)

{

     Py_buffer myBuf;

     if (!PyArg_ParseTuple(args, "s*", &myBuf))

          return NULL;

     char *myString = (char *)myBuf.buf;

     printf("%s\n", myString);

     for (int i = 0; i < myBuf.len; i++)

     {

          printf("%02X ", (unsigned char)myString[i]);

     }

     printf("\n");

     PyBuffer_Release(&myBuf);

     Py_RETURN_NONE;

}

static PyObject *stringEncode(PyObject *self, PyObject *args)

{

     char *name = NULL;

     if (!PyArg_ParseTuple(args, "es", "cp1252", &name))

          return NULL;

     printf("%s \n", name);

     for (int i = 0; name[i]; i++)

     {

          printf("%02X ", (unsigned char)name[i]);

     }

     printf("\n");

     PyMem_Free(name);

     Py_RETURN_NONE;

}

static PyObject *stringEncode2(PyObject *self, PyObject *args)

{

     char *name = NULL;

     Py_ssize_t len;

     if (!PyArg_ParseTuple(args, "es#", "utf-16", &name, &len))

          return NULL;

     printf("%s \n", name);

     for (int i = 0; i < len; i++)

     {

          printf("%02X ", (unsigned char)name[i]);

     }

     printf("\n");

     PyMem_Free(name);

     Py_RETURN_NONE;

}

static PyObject *stringEncodeAllocate(PyObject *self,

                                      PyObject *args)

{

     Py_ssize_t len = 25;

     char *name = malloc(sizeof(char) * (len + 1));

     if (!PyArg_ParseTuple(args, "es#", "cp1252", &name, &len))

          return NULL;

     printf("%d\n", (int)len);

     printf("%s \n", name);

     for (int i = 0; i < len; i++)

     {

          printf("%02X ", (unsigned char)name[i]);

     }

     printf("\n");

     free(name);

     Py_RETURN_NONE;

}

static PyObject *sequenceElements(PyObject *self, PyObject *args)

{

     int number;

     double x, y;

     char *name = NULL;

     if (!PyArg_ParseTuple(args, "(idds)", &number, &x, &y, &name))

          return NULL;

     printf("%d %f %f %s \n", number, x, y, name);

     Py_RETURN_NONE;

}

static PyMethodDef AddMethods[] = {

    {"stringRaw", stringRaw, METH_VARARGS, "an example"},

    {"stringRawLen", stringRawLen, METH_VARARGS, "an example"},

    {"stringPBuffer", stringPBuffer, METH_VARARGS, "an example"},

    {"stringEncode", stringEncode, METH_VARARGS, "an example"},

    {"stringEncode2", stringEncode2, METH_VARARGS, "an example"},

    {"stringEncodeAllocate", stringEncodeAllocate, METH_VARARGS, "an example"},

    {"sequenceElements", sequenceElements, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_example(void)

{

     return PyModule_Create(&addmodule);

}

test.py

import example

example.stringRaw("Hello World")

example.stringRawLen("Hello \0 World")

example.stringPBuffer("Hello \0 World")

example.stringEncode("Hello World")

example.stringEncode("\u2020")

example.stringEncode2("Hello World")

example.stringEncodeAllocate("Hello World")

example.sequenceElements((2,1.2,1.3,"test"))


 Page 81

example.c

This is the combined code from the chapter - the json files are as for example given ealier

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *retInt(PyObject *self, PyObject *args)

{

     int value = -1;

     return Py_BuildValue("I", value);

}

static PyObject *strTostr(PyObject *self, PyObject *args)

{

     char *name = "Brian";

     return Py_BuildValue("s", name);

}

static PyObject *strTostr2(PyObject *self, PyObject *args)

{

     char name[] = "    Brian";

     name[0] = 0xCE;

     name[1] = 0x94;

     return Py_BuildValue("s", name);

}

static PyObject *strTostrLen(PyObject *self, PyObject *args)

{

     char name[] = "   Brian";

     Py_ssize_t len = 5;

     name[0] = 0xCE;

     name[1] = 0x94;

     return Py_BuildValue("s#", name, len);

}

static PyObject *strTobytesLen(PyObject *self, PyObject *args)

{

     char name[] = "   Brian";

     Py_ssize_t len = 5;

     name[0] = 0xCE;

     name[1] = 0x94;

     return Py_BuildValue("y#", name, len);

}

static PyObject *wcharTostrLen(PyObject *self, PyObject *args)

{

     wchar_t name[] = L"   Brian";

     Py_ssize_t len = 5;

     name[0] = 0x0394;

     return Py_BuildValue("u#", name, len);

}

static PyObject *wcharTostrLen2(PyObject *self, PyObject *args)

{

  wchar_t name[] = L"   Brian";

  Py_ssize_t len = 5;

  name[0] = 0xD83E;

  name[1] = 0xDD10;

  return Py_BuildValue("u#", name, len);

}

static PyObject *retTuple(PyObject *self, PyObject *args)

{

  int number = 42;

  double x = 1.2, y = 1.1;

  char *name = "brian";

  return Py_BuildValue("(isdd)", number, name, x, y);

}

static PyObject *retList(PyObject *self, PyObject *args)

{

  int number = 42;

  double x = 1.2, y = 1.1;

  char *name = "brian";

  return Py_BuildValue("[isdd]", number, name, x, y);

}

static PyObject *retDict(PyObject *self, PyObject *args)

{

  int number = 42;

  double x = 1.2, y = 1.1;

  char *name = "brian";

  return Py_BuildValue("{sisssdsd}", "first", number,"second", name,"x", x,"y", y);

}

static PyMethodDef AddMethods[] = {

    {"retInt", retInt, METH_VARARGS, "an example"},

    {"strTostr", strTostr, METH_VARARGS, "an example"},

    {"strTostr2", strTostr2, METH_VARARGS, "an example"},

    {"strTostrLen", strTostrLen, METH_VARARGS, "an example"},

    {"strTobytesLen", strTobytesLen, METH_VARARGS, "an example"},

    {"wcharTostrLen", wcharTostrLen, METH_VARARGS, "an example"},

    {"wcharTostrLen2", wcharTostrLen2, METH_VARARGS, "an example"},

    {"retTuple", retTuple, METH_VARARGS, "an example"},

    {"retList", retList, METH_VARARGS, "an example"},

    {"retDict", retDict, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_example(void)

{

     return PyModule_Create(&addmodule);

}

test.py

import example
print(example.retInt())
print(example.strTostr())
print(example.strTostr2())
print(example.strTostrLen())
print(example.strTobytesLen())
print(example.wcharTostrLen())
#print(example.wcharTostrLen2())
print(example.retTuple())
print(example.retList())
print(example.retDict())
print("end")


 Page 96

example.c

This is the combined code from the chapter - the json files are as for example given ealier

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *Attributes1(PyObject *self, PyObject *args)

{

     PyObject *myObject;

     if (!PyArg_ParseTuple(args, "O", &myObject))

          return NULL;

     PyObject *attribName = Py_BuildValue("s", "myAttribute1");

     PyObject *myAtt1 = PyObject_GetAttr(myObject, attribName);

     Py_XDECREF(attribName);

     return myAtt1;

}

static PyObject *displayAttributes(PyObject *self, PyObject *args)

{

     PyObject *myObject;

     PyObject *myString;

     if (!PyArg_ParseTuple(args, "OO", &myObject, &myString))

          return NULL;

     PyObject *myAtt1 = PyObject_GetAttr(myObject, myString);

     if (PyUnicode_Check(myAtt1))

     {

          const char *mytext = PyUnicode_AsUTF8(myAtt1);

          printf("%s\n", mytext);

     }

     if (PyLong_Check(myAtt1))

     {

          int myValue = PyLong_AsLong(myAtt1);

          printf("%d\n", myValue);

     }

     return myAtt1;

}

static PyObject *Attributes2(PyObject *self, PyObject *args)

{

     PyObject *myObject;

     if (!PyArg_ParseTuple(args, "O", &myObject))

          return NULL;

     PyObject *newValue = PyLong_FromLong(42);

     if (PyObject_SetAttrString(myObject, "myAttribute1", newValue))

          return NULL;

     Py_RETURN_NONE;

}

static PyObject *Attributes3(PyObject *self, PyObject *args)

{

     PyObject *myObject;

     if (!PyArg_ParseTuple(args, "O", &myObject))

          return NULL;

     if (PyObject_HasAttrString(myObject, "myAttribute1"))

     {

          PyObject *myAtt1 = PyObject_GetAttrString(myObject, "myAttribute1");

          if (PyLong_Check(myAtt1))

          {

               int myValue = PyLong_AsLong(myAtt1);

               printf("%d\n", myValue);

          }

     }

     Py_RETURN_NONE;

}

static PyObject *Attributes4(PyObject *self, PyObject *args)

{

  PyObject *myObject;

  if (!PyArg_ParseTuple(args, "O", &myObject))

    return NULL;

  PyObject *main = PyImport_AddModule("__main__");

  PyObject *maindict = PyModule_GetDict(main);

  PyObject *myclass = PyDict_GetItemString(maindict, "myClass");

  if (PyObject_IsInstance(myObject, myclass))

  {

    PyObject *myAtt1 = PyObject_GetAttrString(myObject, "myAttribute1");

    if (PyLong_Check(myAtt1))

    {

      int myValue = PyLong_AsLong(myAtt1);

      printf("%d\n", myValue);

    }

    Py_XDECREF(myAtt1);

  }

  Py_RETURN_NONE;

}

static PyMethodDef AddMethods[] = {

    {"Attributes1", Attributes1, METH_VARARGS, "an example"},

    {"displayAttributes", displayAttributes, METH_VARARGS, "an example"},

    {"Attributes2", Attributes2, METH_VARARGS, "an example"},

    {"Attributes3", Attributes3, METH_VARARGS, "an example"},

    {"Attributes4", Attributes4, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_example(void)

{

     return PyModule_Create(&addmodule);

}

test.py

import example

class myClass:

    myAttribute1=10

    myAttribute2="Brian"

myInstance=myClass()

print(example.Attributes1(myInstance))

value=example.displayAttributes(myInstance,"myAttribute1")

print(value)

value=example.displayAttributes(myInstance,"myAttribute2")

print(value)

example.Attributes2(myInstance)

print(myInstance.myAttribute1)

example.Attributes3(myInstance)

example.Attributes4(myInstance)


Page 113

example.c

This is the combined code from the chapter - the json files are as for example given ealier

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *tuple1(PyObject *self, PyObject *args)

{

     PyObject *myTuple = PyTuple_New(10);

     for (int i = 0; i < 10; i++)

     {

          PyObject *item = PyLong_FromLong(i);

          PyTuple_SET_ITEM(myTuple, i, item);

     }

     return myTuple;

}

static PyObject *list1(PyObject *self, PyObject *args)

{

     PyObject *mylist = PyList_New(10);

     for (int i = 0; i < 10; i++)

     {

          PyObject *item = PyLong_FromLong(i);

          PyList_SetItem(mylist, i, item);

     }

     return mylist;

}

static PyObject *list2(PyObject *self, PyObject *args)

{

     PyObject *itemlist = PyList_New(0);

     for (int i = 0; i < 10; i++)

     {

          PyObject *item = PyLong_FromLong(i);

          PyList_Append(itemlist, PyLong_FromLong(i));

          Py_DECREF(PyList_GetItem(itemlist, i));

     }

     return itemlist;

}

static PyObject *dict1(PyObject *self, PyObject *args)

{

     PyObject *mydict = PyDict_New();

     PyObject *val = PyLong_FromLong(42333);

     PyObject *key = PyUnicode_DecodeUTF8("Item0", 5, NULL);

     PyDict_SetItem(mydict, key, val);

     Py_DECREF(val);

     Py_DECREF(key);

     return mydict;

}

static PyObject *tuple2(PyObject *self, PyObject *args)

{

     PyObject *myTuple;

     if (!PyArg_ParseTuple(args, "O", &myTuple))

          return NULL;

     int myarray[10];

     for (int i = 0; i < 10; i++)

     {

          PyObject *item = PyTuple_GetItem(myTuple, i);

          myarray[i] = PyLong_AsLong(item);

          printf("%d ", myarray[i]);

     }

     printf("\n");

     Py_RETURN_NONE;

}

static PyObject *list3(PyObject *self, PyObject *args)

{

     PyObject *mylist;

     if (!PyArg_ParseTuple(args, "O", &mylist))

          return NULL;

     PyObject *itemlist = PyList_New(4);

     PyList_SetItem(itemlist, 0, PyLong_FromLong(10));

     PyList_SetItem(itemlist, 1, PyLong_FromLong(11));

     PyList_SetItem(itemlist, 2, PyLong_FromLong(12));

     PyList_SetItem(itemlist, 3, PyLong_FromLong(13));

     PyList_SetSlice(mylist, 3, 5, itemlist);

     Py_DECREF(itemlist);

     Py_RETURN_NONE;

}

static PyObject *listIterator(PyObject *self, PyObject *args)

{

     PyObject *mylist;

     if (!PyArg_ParseTuple(args, "O", &mylist))

          return NULL;

     PyObject *myIter = PyObject_GetIter(mylist);

     printf("%d ", PyLong_AsLong((PyIter_Next(myIter))));

     printf("%d ", PyLong_AsLong((PyIter_Next(myIter))));

     printf("%d ", PyLong_AsLong((PyIter_Next(myIter))));

     printf("%d ", PyLong_AsLong((PyIter_Next(myIter))));

     printf("\n");

     Py_DECREF(myIter);

     Py_RETURN_NONE;

}

static PyObject *listFor(PyObject *self, PyObject *args)

{

     PyObject *myList;

     if (!PyArg_ParseTuple(args, "O", &myList))

          return NULL;

     PyObject *myIter = PyObject_GetIter(myList);

     for (PyObject *item = PyIter_Next(myIter); item != NULL; item = PyIter_Next(myIter))

     {

          printf("%d ", PyLong_AsLong(item));

          Py_DECREF(item);

     }

     printf("\n");

     Py_DECREF(myIter);

     Py_RETURN_NONE;

}

static PyObject *listWhile(PyObject *self, PyObject *args)

{

     PyObject *myList;

     if (!PyArg_ParseTuple(args, "O", &myList))

          return NULL;

     PyObject *myIter = PyObject_GetIter(myList);

     PyObject *item;

     while (item = PyIter_Next(myIter))

     {

          printf("%d ", PyLong_AsLong(item));

          Py_DECREF(item);

     }

     Py_DECREF(myIter);

     printf("\n");

     Py_DECREF(myIter);

     Py_RETURN_NONE;

}

static PyMethodDef AddMethods[] = {

    {"tuple1", tuple1, METH_VARARGS, "an example"},

    {"list1", list1, METH_VARARGS, "an example"},

    {"list2", list2, METH_VARARGS, "an example"},

    {"dict1", dict1, METH_VARARGS, "an example"},

    {"tuple2", tuple2, METH_VARARGS, "an example"},

    {"list3", list3, METH_VARARGS, "an example"},

    {"listIterator", listIterator, METH_VARARGS, "an example"},

    {"listFor", listFor, METH_VARARGS, "an example"},

    {"listWhile", listWhile, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_example(void)

{

     return PyModule_Create(&addmodule);

}

test.py

import example

import sys

#print(example.tuple1())

print(example.list1())

myList=example.list2()

print(myList)

print("ref count=",sys.getrefcount(myList[0])-1)

myDict=example.dict1()

print(myDict)

print("ref count=",sys.getrefcount(myDict["Item0"])-1)

print("ref count=",sys.getrefcount(myDict)-1)



myTuple=example.tuple1()

print(myTuple)

example.tuple2(myTuple)

mylist=[0,1,2,3,4,5,6,7,8,9]

example.list3(mylist)

print(myList)

mylist=[0,1,2,3,4,5,6,7,8,9]

example.listIterator(mylist)

example.listFor(mylist)

example.listWhile(mylist)

 


Page 118

 

exception.py

total=0

class MyNumberError(ArithmeticError):

    def __init__(self, message,):

        super(MyNumberError, self).__init__(message)



def myFunc(x,y):

    global total

    total=total+1

    print("in myFunc")

    raise MyNumberError("Number not 42")

    return 1

result=myFunc(1,1)

try:

    result=myFunc(1,1)

except MyNumberError:

    print("Can't divide by zero")

    total=total-1

  #  result=myFunc(1,1)

#print(result)

print(total)

Page 123

example.c

This is the combined code from the chapter - the json files are as for example given ealier

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *exception1(PyObject *self, PyObject *args)

{

     PyObject *x = PyLong_FromLong(1);

     PyObject *y = PyLong_FromLong(0);

     PyObject *ans = PyNumber_TrueDivide(x, y);

     if (ans == NULL)

     {

          Py_DECREF(x);

          Py_DECREF(y);

          return NULL;

     }

     PyObject *z = PyLong_FromLong(1);

     PyObject *ans2 = PyNumber_TrueDivide(x, z);

     Py_DECREF(x);

     Py_DECREF(y);

     Py_DECREF(z);

     return ans;

}

static PyObject *exception2(PyObject *self, PyObject *args)

{

     PyErr_SetString(PyExc_ZeroDivisionError, "A Dummy divide error has occurred");

     return NULL;

}

static PyObject *myCustomException;

static PyObject *exception3(PyObject *self, PyObject *args)

{

     PyErr_SetString(myCustomException, "A Custom error has occurred");

     return NULL;

}

static PyObject *exception4(PyObject *self, PyObject *args)

{

     PyObject *x = PyLong_FromLong(1);

     PyObject *y = PyLong_FromLong(0);

     PyObject *ans = PyNumber_TrueDivide(x, y);

     if (ans == NULL)

     {

          PyErr_Clear();

          PyObject *z = PyLong_FromLong(1);

          ans = PyNumber_TrueDivide(x, z);

          Py_DECREF(z);

     }

     Py_DECREF(x);

     Py_DECREF(y);

     return ans;

}

static PyObject *exception5(PyObject *self, PyObject *args)

{

     PyObject *x = PyLong_FromLong(1);

     PyObject *y = PyLong_FromLong(0);

     PyObject *ans = PyNumber_TrueDivide(x, y);

     if (PyErr_Occurred() != NULL)

     {

          if(PyErr_ExceptionMatches(PyExc_ZeroDivisionError)){

               PyErr_Clear();

               PyObject *z = PyLong_FromLong(1);

               ans = PyNumber_TrueDivide(x, z);

               Py_DECREF(z);

          }

     }

     Py_DECREF(x);

     Py_DECREF(y);

     return ans;

}

static PyObject *list1(PyObject *self, PyObject *args)

{

  PyObject *myList;

  if (!PyArg_ParseTuple(args, "O", &myList))

    return NULL;

  printf("myList %ld\n", Py_REFCNT(myList));

  PyObject *temp = PyList_GetItem(myList, 0);

  printf("item zero %ld\n", Py_REFCNT(temp));

  PyObject *myList2 = PySequence_InPlaceConcat(myList, myList);

  temp = PyList_GetItem(myList, 0);

  temp = PyList_GetItem(myList, 0);

  printf("myList %ld\n", Py_REFCNT(myList));

  printf("item zero %ld\n", Py_REFCNT(temp));

  Py_RETURN_NONE;

}



static PyMethodDef AddMethods[] = {

    {"exception1", exception1, METH_VARARGS, "an example"},

    {"exception2", exception2, METH_VARARGS, "an example"},

    {"exception3", exception3, METH_VARARGS, "an example"},

    {"exception4", exception4, METH_VARARGS, "an example"},

    {"exception5", exception5, METH_VARARGS, "an example"},

    {"list1", list1, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_example(void)

{

     PyObject *m;

     m = PyModule_Create(&addmodule);

     if (m == NULL)

          return NULL;

     myCustomException = PyErr_NewException("example.myCustomException", NULL, NULL);

     if (PyModule_AddObjectRef(m, "myCustomException", myCustomException) < 0)

     {

          Py_CLEAR(myCustomException);

          Py_DECREF(m);

          return NULL;

     }

     return m;

}

test.py

import example

import gc

#ans=example.exception1()

#print(ans)

#try:

#    ans=example.exception2()

#except ZeroDivisionError as err:

#    print(err)

try:

   ans=example.exception3()

except example.myCustomException as err:

    print(err)



try:

    ans=example.exception4()

except ZeroDivisionError as err:

    print(err)

print(ans)

try:

    ans=example.exception5()

except ZeroDivisionError as err:

    print(err)

print(ans)

print(gc.get_objects())

gc.collect()

myList=[257,1,2,3,4,5,6,7,8,9]

gc.collect()

example.list1(myList)

print(myList)


Page 148

example.c

This is the combined code from the chapter - the json files are as for example given ealier

 

 

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *bytes1(PyObject *self, PyObject *args)

{

     char *myString = "Hello World";

     PyObject *myBytes = PyBytes_FromString(myString);

     return myBytes;

}

static PyObject *bytes2(PyObject *self, PyObject *args)

{

     PyObject *myBytes;

     if (!PyArg_ParseTuple(args, "O", &myBytes))

          return NULL;

     Py_ssize_t len = PyBytes_Size(myBytes);

     for (int i = 1; i < len; i++)

     {

          PyObject *item = PySequence_GetItem(myBytes, i);

          char c = (char)PyLong_AsLong(item);

          printf("%X  ", c);

     }

     printf("\n");

     PyObject *myByteArray = PyByteArray_FromStringAndSize(PyBytes_AsString(myBytes), PyBytes_Size(myBytes));

     char *HelloMessage = "Hello World";

     PyObject *insert = PyByteArray_FromStringAndSize(HelloMessage, strlen(HelloMessage));

     PySequence_SetSlice(myByteArray, 3, 7, insert);

     return myByteArray;

}

static PyObject *string1(PyObject *self, PyObject *args)

{

     PyObject *uni1 = PyUnicode_New(10, 255);

     PyUnicode_Fill(uni1, 0, 10, 120);

     PyUnicode_WriteChar(uni1, 0, 72);

     return uni1;

}

static PyObject *string2(PyObject *self, PyObject *args)

{

     PyObject *myString = PyUnicode_FromString("Spam, Spam, Spam, Spam… Lovely Spam! Wonderful Spam!");

     int len = PyUnicode_GET_LENGTH(myString);

     Py_UCS4 *buf = PyMem_Malloc(sizeof(Py_UCS4) * (len + 1));

     PyUnicode_AsUCS4(myString, buf, 100, 1);

     for (int i = 0; buf[i]; i++)

     {

          printf("%04X ", buf[i]);

     }

     PyMem_Free(buf);

     printf("\n\n");

     buf = PyUnicode_AsUCS4Copy(myString);

     for (int i = 0; buf[i]; i++)

     {

          printf("%04X ", buf[i]);

     }

     printf("\n\n");

     PyMem_Free(buf);

     Py_DECREF(myString);

     Py_RETURN_NONE;

}

static PyObject *string3(PyObject *self, PyObject *args)

{

     PyObject *myString = PyUnicode_FromString("Spam, Spam, Spam, Spam… Lovely Spam! Wonderful Spam!");

     int len = PyUnicode_GET_LENGTH(myString);

     PyObject *substr = PyUnicode_FromString("Lovely");

     Py_ssize_t pos = PyUnicode_Find(myString, substr, 0, len, 1);

     printf("position of Lovely = %ld\n", pos);

     pos = PyUnicode_FindChar(myString, 0x0000006D, 0, len, 1);

     printf("position of first m %ld\n", pos);

     substr = PyUnicode_FromString("Spam");

     Py_ssize_t result = PyUnicode_Tailmatch(myString, substr, 0, len, -1);

     printf("prefix match %ld\n", result);

     substr = PyUnicode_FromString("Spam");

     result = PyUnicode_Contains(myString, substr);

     printf("Contains Spam %ld\n", result);

     Py_ssize_t count = PyUnicode_Count(myString, substr, 0, len);

     printf("Count of how many spam(s) %ld\n", count);

     PyObject *test = PyUnicode_FromString("Spam");

     result = PyUnicode_Compare(substr, test);

     printf("compare to Spam %ld\n", result);

     result = PyUnicode_CompareWithASCIIString(substr, "Spam");

     printf("compare to Spam %ld\n", result);

     PyObject *logic = PyUnicode_RichCompare(substr, test, Py_EQ);

     if (Py_IsTrue(logic))

     {

          printf("Strings are equal\n");

     }

     else

     {

          printf("Strings are not equal\n");

     }

     Py_RETURN_NONE;

}

static PyObject *string4(PyObject *self, PyObject *args)

{

     PyObject *myString = PyUnicode_FromString("Spam, Spam, Spam, Spam . . .Lovely Spam! Wonderful Spam!");

     PyObject *bytesUTF8 = PyUnicode_AsUTF8String(myString);

     PyObject *bytesUTF16 = PyUnicode_AsUTF16String(myString);

     PyObject *bytesUTF32 = PyUnicode_AsUTF32String(myString);

     Py_ssize_t len = PyBytes_Size(bytesUTF32);

     for (int i = 0; i < len; i++)

     {

          PyObject *item = PySequence_GetItem(bytesUTF32, i);

          int c = PyLong_AsLong(item);

          printf("%02X  ", c);

     }

     printf("\n");

     char *buffer;

     PyBytes_AsStringAndSize(bytesUTF32, &buffer, &len);

     PyObject *decodeStr = PyUnicode_DecodeUTF32(buffer, len, NULL, NULL);

     return decodeStr;

}

static PyObject *string5(PyObject *self, PyObject *args)

{

     PyObject *myString = PyUnicode_New(1, 1114111);

     PyUnicode_WriteChar(myString, 0, 0x2020);

     PyObject *myBytes = PyUnicode_AsEncodedString(myString, "cp1252", NULL);

     char *buffer;

     Py_ssize_t len;

     PyBytes_AsStringAndSize(myBytes, &buffer, &len);

     printf("%X \n", buffer[0]);

     printf("%s \n", buffer);

     Py_DECREF(myBytes);

     return myString;

}

static PyObject *string6(PyObject *self, PyObject *args)

{

  PyObject *myString = PyUnicode_FromString("† Spam, Spam, Spam, Spam . . .Lovely Spam! Wonderful Spam!");

  PyObject *myBytes = PyUnicode_AsEncodedString(myString, "raw_unicode_escape", NULL);

  Py_DECREF(myString);

  return myBytes;

}

static PyMethodDef AddMethods[] = {

    {"bytes1", bytes1, METH_VARARGS, "an example"},

    {"bytes2", bytes2, METH_VARARGS, "an example"},

    {"string1", string1, METH_VARARGS, "an example"},

    {"string2", string2, METH_VARARGS, "an example"},

    {"string3", string3, METH_VARARGS, "an example"},

    {"string4", string4, METH_VARARGS, "an example"},

    {"string5", string5, METH_VARARGS, "an example"},

    {"string6", string6, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_example(void)

{

     return PyModule_Create(&addmodule);

}

 test.py

import example
mybytes=example.bytes1()
print(mybytes)
print()

mybytes=example.bytes2(b"My long message")
print(mybytes)

print(example.string1())
print()
example.string2()
print()
example.string3()
print()
print(example.string4())

print()
result=example.string5()
print(result)
print()
result=example.string6()
print(result)


 

Page 157

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *exampleFunction(PyObject *self, PyObject *args)

{

     // example function code

}

static PyMethodDef AddMethods[] = {

    {"exampleFunction", exampleFunction, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static PyObject *myFunc(PyObject *self, PyObject *args)

{

     printf("hello world\n");

     Py_RETURN_NONE;

}

static PyObject *myFunc2(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)

{

     for (int i = 0; i < nargs; i++)

     {

          const char *myString = PyUnicode_AsUTF8(args[i]);

          printf("%s\n", myString);

     }

     Py_ssize_t nKwds = PyTuple_Size(kwnames);

     for (int i = 0; i < nKwds; i++)

     {

          const char *myValue = PyUnicode_AsUTF8(args[i + nargs]);

          const char *myKeyword = PyUnicode_AsUTF8(PyTuple_GetItem(kwnames, i));

          printf("Keyword = %s, Value = %s \n", myKeyword, myValue);

     }

     Py_RETURN_NONE;

}

static PyMethodDef myFunc_def = {

    "myFunc",

    myFunc,

    METH_VARARGS,

    "the doc string"};

static PyMethodDef myFunc2_def = {

    "myFunc2",

    (PyCFunction)myFunc2,

    METH_FASTCALL | METH_KEYWORDS,

    "the doc string"};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

     PyObject *m = PyModule_Create(&myModule);

     if (m == NULL)

          return NULL;

     // Add a int

     PyObject *myValue = PyLong_FromLong(42);

     PyModule_AddObject(m, "myValue", myValue);

     // Add a list

     PyObject *myList = PyList_New(0);

     PyModule_AddObject(m, "myList", myList);

     // Add a function

     PyObject *myPyFun = PyCFunction_New(&myFunc_def, m);

     PyModule_AddObject(m, "myFunc1", myPyFun);

     // Add a fastcall function

     PyObject *myPyFun2 = PyCFunction_New(&myFunc2_def, m);

     PyModule_AddObject(m, "myFunc2", myPyFun2);

     //Add a function in another module

     PyObject *math=PyImport_ImportModule("math");

     PyObject *mathdict = PyModule_GetDict(math);

     PyObject *myFunction = PyDict_GetItemString(mathdict, "sqrt");

     PyModule_AddObject(m, "myFunc3", myFunction);

     return m;

}

test.py

import example
print("module constant",example.myValue)
example.myValue=43
print("module constant",example.myValue)
print(example.myList)
example.myList.append("spam")
print(example.myList)
print(example.myFunc1())
example.myFunc2("Hello","World",MyKeyWord="myValue")
print(example.myFunc3(2))
print(example.myFunc3.__name__)

 

 

Page 160

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

int exec(PyObject *m)

{

  PyObject *myValue = PyLong_FromLong(42);

  PyModule_AddObject(m, "myValue", myValue);

  return 0;

}

PyObject *create(PyObject *spec, PyModuleDef *def)

{

  PyObject *res=PyObject_GetAttrString(spec,"origin");

  printf("%s\n",PyUnicode_AsUTF8(res));

  PyObject *m= PyModule_New("example");

  return m;

}

PyModuleDef_Slot twoPhase[] = {

    {Py_mod_create, create},

    {Py_mod_exec, exec},

    {0, 0}};

static struct PyModuleDef myModuledef = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    0,

    NULL,

    twoPhase};

PyMODINIT_FUNC PyInit_example(void)

{

  return PyModuleDef_Init(&myModuledef);

}

test.py

import example
print(example.myValue)

Page 164

 example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

struct myData

{

  int count;

  char name[20];

};

static struct myData myModuleData = {42, "spam"};

static PyObject *myFunc(PyObject *self, PyObject *args)

{

  printf("module data %d , %s\n", myModuleData.count, myModuleData.name);

  myModuleData.count++;

  struct myData *myModData = (struct myData *)PyModule_GetState(self);

  printf("module data %d , %s\n", myModData->count, myModData->name);

  myModData->count++;

  Py_RETURN_NONE;

}

static PyMethodDef myFunc_def = {

    "myFunc",

    myFunc,

    METH_VARARGS,

    "the doc string"};

int exec(PyObject *m)

{

  struct myData *myModData = (struct myData *)PyModule_GetState(m);

  myModData->count = 42;

  strcpy(myModData->name, "spam");

  PyObject *myValue = PyLong_FromLong(42);

  PyModule_AddObject(m, "myValue", myValue);

  PyObject *myPyFun = PyCFunction_New(&myFunc_def, m);

  PyModule_AddObject(m, "myFunc", myPyFun);

  return 0;

}

PyObject *create(PyObject *spec, PyModuleDef *def)

{

  PyObject *res = PyObject_GetAttrString(spec, "origin");

  printf("%s\n", PyUnicode_AsUTF8(res));

  PyObject *m = PyModule_New("example");  

  return m;

}



void freeModule(void *m){

    struct myData *myModData = (struct myData *)PyModule_GetState(m);

    PyMem_Free(myModData);

}

PyModuleDef_Slot twoPhase[] = {

    {Py_mod_create, create},

    {Py_mod_exec, exec},

    {0, 0}};

static struct PyModuleDef myModuledef = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    sizeof(struct myData),

    NULL,

    twoPhase,

    NULL,

    NULL,

    freeModule};

PyMODINIT_FUNC PyInit_example(void)

{

  return PyModuleDef_Init(&myModuledef);

}

test.py

import example
example.myFunc()
example.myFunc()

 


 Page 172

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyTypeObject MyType1 = {

    PyVarObject_HEAD_INIT(NULL, 0)

    .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT |  Py_TPFLAGS_DISALLOW_INSTANTIATION

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
myclass=example.MyClass
print(myclass)
print(myclass.__dict__)

Page 173

example.c
 

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyTypeObject MyType1 = {

    PyVarObject_HEAD_INIT(NULL, 0)

    .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(PyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
myInst=example.MyClass()
print(myInst)
print(myInst.__dir__())
print(myInst.__sizeof__())

Page 176

exampe.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *myFunc(PyObject *self, PyObject *args)

{

  printf("hello world\n");

  Py_RETURN_NONE;

}

static PyMethodDef myFunc_def = {

    "myFunc",

    myFunc,

    METH_VARARGS,

    "the doc string"};

static PyTypeObject MyType1 = {

    PyVarObject_HEAD_INIT(NULL, 0)

        .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(PyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  PyObject *mydict = PyDict_New();

  PyObject *val = PyLong_FromLong(42);

  PyDict_SetItemString(mydict, "myValue", val);

  Py_DECREF(val);

  PyObject *myPyFun = PyCFunction_New(&myFunc_def, (PyObject *)&MyType1);

  PyDict_SetItemString(mydict, "myFunc", myPyFun);

  MyType1.tp_dict = mydict;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

 

test.py

import example
example.MyClass.myFunc()
myInst=example.MyClass()
myInst.myFunc()

 Page 177

 example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

typedef struct

{

  PyObject_HEAD

      PyObject *dict;

} MyObject;

static PyObject *myFunc(PyObject *self, PyObject *args)

{

  printf("hello world\n");

  Py_RETURN_NONE;

}

static PyMethodDef myFunc_def = {

    "myFunc",

    myFunc,

    METH_VARARGS,

    "the doc string"};

static PyTypeObject MyType1 = {

    PyVarObject_HEAD_INIT(NULL, 0)

        .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_dictoffset=offsetof(MyObject, dict),

    .tp_new = PyType_GenericNew,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  PyObject *mydict = PyDict_New();

  PyObject *val = PyLong_FromLong(42);

  PyDict_SetItemString(mydict, "myValue", val);

  Py_DECREF(val);

  PyObject *myPyFun = PyCFunction_New(&myFunc_def, (PyObject *)&MyType1);

  PyDict_SetItemString(mydict, "myFunc", myPyFun);

  MyType1.tp_dict = mydict;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py 

import example
example.MyClass.myFunc()
myInst=example.MyClass()
myInst.myFunc()
myInst.myValue=43
print(myInst.myValue)
myInst.myVal1=42
print(myInst.myVal1)

Page  180

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

typedef struct

{

  PyObject_HEAD

      PyObject *dict;

} MyObject;

static PyObject *myFunc(PyObject *self, PyObject *args)

{

  printf("hello world\n");

  Py_RETURN_NONE;

}

static PyMethodDef myFunc_def = {

    "myFunc",

    myFunc,

    METH_VARARGS,

    "the doc string"};

static PyObject *Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)

{

  MyObject *self;

  self = (MyObject *)type->tp_alloc(type, 0);

  return (PyObject *)self;

}

static int Custom_init(MyObject *self, PyObject *args, PyObject *kwds)

{

  PyObject *myPyFunc = PyCFunction_New(&myFunc_def, (PyObject *)self);

  PyObject *myPyMethod = PyInstanceMethod_New(myPyFunc);

  int res = PyObject_SetAttrString((PyObject *)self, "MyMethod", myPyMethod);

  return 0;

}

static PyTypeObject MyType1 = {

    PyVarObject_HEAD_INIT(NULL, 0)

        .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_dictoffset = offsetof(MyObject, dict),

    .tp_new = Custom_new,

    .tp_init = (initproc)Custom_init,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  PyObject *mydict = PyDict_New();

  PyObject *val = PyLong_FromLong(42);

  PyDict_SetItemString(mydict, "myValue", val);

  Py_DECREF(val);

  PyObject *myPyFun = PyCFunction_New(&myFunc_def, (PyObject *)&MyType1);

  PyDict_SetItemString(mydict, "myFunc", myPyFun);

  MyType1.tp_dict = mydict;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
example.MyClass.myFunc()
myInst=example.MyClass()
myInst.myFunc()
myInst.myValue=43
print(myInst.myValue)
myInst.myVal1=42
print(myInst.myVal1)
myInst.MyMethod()

Page 185

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyObject_HEAD

  int myVal;

} MyObject;

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};



static PyMemberDef myMemberdef = {

    "MyVar",

    T_INT,

    offsetof(MyObject, myVal),

    0,

    "MyInstanceAttr"};

static PyMethodDef myFunc_def = {

    "myFunc",

    (PyCFunction)myFunc,

    METH_VARARGS,

    "the doc string"};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new =PyType_GenericNew,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  PyObject *mydict=PyDict_New();

  PyObject *myMethodDesc = PyDescr_NewMethod(&MyType1, &myFunc_def);

  int res = PyDict_SetItemString(mydict, "MyMethod", myMethodDesc);

  PyObject *myMemberDesc = PyDescr_NewMember(&MyType1, &myMemberdef);

  res = PyDict_SetItemString(mydict, "MyVar", myMemberDesc);

  MyType1.tp_dict=mydict;

  res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

 test.py

import example

myInst=example.MyClass()
myInst.MyMethod()
myInst.MyVar=43
print(myInst.MyVar)

Page  187

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyObject_HEAD

  int myVal;

} MyObject;

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};



static PyMemberDef myMemberdef[] = {

   { "MyVar",T_INT,offsetof(MyObject, myVal),0,"MyInstanceAttr"},

   {NULL}

    };

static PyMethodDef myMethodDef[] = {

  {"MyMethod",(PyCFunction)myFunc,METH_VARARGS,"the doc string"},

  {NULL}

    };

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

    .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example

myInst=example.MyClass()
myInst.MyMethod()
myInst.MyVar=43
print(myInst.MyVar)

Page 190

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyObject_HEAD

      PyObject *myProp;

} MyObject;

static PyObject *getVal(MyObject *self, void *extra)

{

  return Py_NewRef(self->myProp);

}

int setVal(MyObject *self, PyObject *val, void *extra)

{

  Py_XSETREF(self->myProp, Py_XNewRef(val));

  return 0;

}

static PyGetSetDef myGetSetDef[] = {

    {"myProperty", (getter)getVal, (setter)setVal, "Example get set", NULL},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_getset = myGetSetDef,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example

myInst=example.MyClass()
myInst.myProperty=42
print(myInst.myProperty)


 Page 194

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

     PyObject_HEAD int myVal;

} MyObject;

static void Custom_dealloc(MyObject *self)

{

     printf("destructor called\n");

     Py_TYPE(self)->tp_free((PyObject *)self);

}

static PyObject *myFunc(MyObject *self, PyObject *args)

{

     printf("%d\n", self->myVal);

     printf("hello world\n");

     Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

    .tp_dealloc = (destructor)Custom_dealloc,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

     PyObject *m = PyModule_Create(&myModule);

     if (m == NULL)

          return NULL;

     int res = PyType_Ready(&MyType1);

     PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

     return m;

}

test.py

import example
myinst1=example.MyClass()
myinst1.MyVar=42
print(myinst1.MyVar)
myInst1=None

Page 196

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyObject_HEAD

  int myVal;

  PyObject *myAttr;

} MyObject;

static void Custom_dealloc(MyObject *self)

{

     printf("destructor called\n");

     Py_TYPE(self)->tp_free((PyObject *)self);

}

static PyObject *myFunc(MyObject *self, PyObject *args)

{

     printf("%d\n", self->myVal);

     printf("hello world\n");

     Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0,"MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0,"MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

    .tp_dealloc = (destructor)Custom_dealloc,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

     PyObject *m = PyModule_Create(&myModule);

     if (m == NULL)

          return NULL;

     int res = PyType_Ready(&MyType1);

     PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

     return m;

}

 test.py

import example
myInst1=example.MyClass()
myInst1.MyAttr=myInst1
myInst1=None
print("end")
while True:
     pass

Page 197

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

    PyObject_HEAD int myVal;

    PyObject *myAttr;

    PyObject *weaklist;

} MyObject;

static void Custom_dealloc(MyObject *self)

{

    printf("destructor called\n");

    Py_TYPE(self)->tp_free((PyObject *)self);

}

static PyObject *myFunc(MyObject *self, PyObject *args)

{

    printf("%d\n", self->myVal);

    printf("hello world\n");

    Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0, "MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

    .tp_dealloc = (destructor)Custom_dealloc,

    .tp_weaklistoffset = offsetof(MyObject, weaklist),

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

    PyObject *m = PyModule_Create(&myModule);

    if (m == NULL)

        return NULL;

    int res = PyType_Ready(&MyType1);

    PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

    return m;

}

test.py

import example
import weakref
myInst1=example.MyClass()
myInst1.MyAttr=weakref.ref(myInst1)
myInst1=None
print("end")
while True:
    pass

 Page 199

example.c 

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyObject_HEAD int myVal;

  PyObject *myAttr;

} MyObject;

static void Custom_dealloc(MyObject *self)

{

  printf("destructor called\n");

  PyObject *error_type,*error_value, *error_traceback;

  PyErr_Fetch(&error_type, &error_value, &error_traceback);

  PyObject_GC_UnTrack(self);

  Py_TYPE(self)->tp_clear((PyObject *)self);

  PyObject_GC_Del(self);

  PyErr_Restore(error_type, error_value, error_traceback);  

}

static int Custom_clear(MyObject *self)

{

  printf("clear called\n");

  Py_CLEAR(self->myAttr);

  return 0;

}

static int Custom_traverse(MyObject *self, visitproc visit, void *arg)

{

  printf("traverse called\n");

  Py_VISIT(self->myAttr);

  return 0;

}

static int Custom_init(MyObject *self, PyObject *args, PyObject *kwds)

{

  self->myVal = 0;

  self->myAttr = Py_None;

  Py_XINCREF(Py_None);

  return 0;

}

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0, "MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_init = (initproc)Custom_init,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

    .tp_clear = (inquiry)Custom_clear,

    .tp_traverse = (traverseproc)Custom_traverse,

    .tp_dealloc = (destructor)Custom_dealloc,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

 

test.py

import example
import gc

myInst1=example.MyClass()
print(gc.is_tracked(myInst1))
myInst1.MyAttr=myInst1
myInst1=None
print(gc.get_count())
gc.collect()
print(gc.get_count())

Page 203

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

static PyTypeObject MyType1;

typedef struct

{

  PyObject_HEAD int myVal;

  PyObject *myAttr;

} MyObject;

static void Custom_dealloc(MyObject *self)

{

  printf("destructor called\n");

  PyObject *error_type,

      *error_value, *error_traceback;

  PyErr_Fetch(&error_type, &error_value, &error_traceback);

  PyObject_GC_UnTrack(self);

  Py_TYPE(self)->tp_clear((PyObject *)self);

  PyObject_GC_Del(self);

  PyErr_Restore(error_type, error_value, error_traceback);

}

static void Custom_finalizer(MyObject *self)

{

  printf("finalizer called\n");

  if (PyObject_GC_IsFinalized((PyObject *)self))

    return;

  PyObject *error_type,

      *error_value, *error_traceback;

  PyErr_Fetch(&error_type, &error_value, &error_traceback);

  PyObject_GC_UnTrack(self);

  Py_TYPE(self)->tp_clear((PyObject *)self);

  PyObject_GC_Del(self);

  PyErr_Restore(error_type, error_value, error_traceback);

}

static int Custom_clear(MyObject *self)

{

  printf("clear called\n");

  Py_CLEAR(self->myAttr);

  return 0;

}

static int Custom_traverse(MyObject *self, visitproc visit, void *arg)

{

  printf("traverse called\n");

  Py_VISIT(self->myAttr);

  return 0;

}

static int Custom_init(MyObject *self, PyObject *args, PyObject *kwds)

{

  self->myVal = 0;

  self->myAttr = Py_None;

  Py_XINCREF(Py_None);

  return 0;

}

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0, "MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_init = (initproc)Custom_init,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

    .tp_clear = (inquiry)Custom_clear,

    .tp_traverse = (traverseproc)Custom_traverse,

    .tp_finalize = (destructor)Custom_finalizer,

    .tp_dealloc = (destructor)Custom_dealloc,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
import gc

myInst1=example.MyClass()
print(gc.is_tracked(myInst1))
myInst1.MyAttr=myInst1
myInst1=None
print(gc.get_count())
gc.collect()
print(gc.get_count())

Page 205

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

     PyObject_HEAD

     int myVal;

} MyObject;

static PyObject *myFunc(MyObject *self, PyObject *args)

{

     printf("%d\n", self->myVal);

     printf("hello world\n");

     Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static struct PyModuleDef myModule = {PyModuleDef_HEAD_INIT, "example", "C library to test API", -1, NULL};

PyMODINIT_FUNC PyInit_example(void)

{

     PyObject *m = PyModule_Create(&myModule);

     if (m == NULL)

          return NULL;

     static PyType_Slot mySlots[] = {

         {Py_tp_doc, "My Custom object"},

         {Py_tp_members, myMemberdef},

         {Py_tp_methods, myMethodDef},

         {0, NULL}};

     PyType_Spec mySpec = {

         "example.myObject",

         sizeof(MyObject),

         0,

         Py_TPFLAGS_DEFAULT,

         mySlots};

     PyTypeObject *MyType1 = (PyTypeObject *)PyType_FromSpec(&mySpec);

     PyModule_AddObject(m, "MyClass", (PyObject *)MyType1);

     return m;

}

test.py

import example
myInst1=example.MyClass()
myInst1.MyVar=42
print(myInst1.MyVar)
myInst1.MyMethod()
example.MyClass.myNewVar=43
print(example.MyClass.myNewVar)

 

 

 

Page 206

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyObject_HEAD int myVal;

  PyObject *myAttr;

} MyObject;

static void Custom_dealloc(MyObject *self)

{

  printf("destructor called\n");

  PyObject *error_type, *error_value, *error_traceback;

  PyErr_Fetch(&error_type, &error_value, &error_traceback);

  PyObject_GC_UnTrack(self);

  Py_TYPE(self)->tp_clear((PyObject *)self);

  PyObject_GC_Del(self);

  PyErr_Restore(error_type, error_value, error_traceback);

}

static void Custom_finalizer(MyObject *self)

{

  printf("finalizer called\n");

  if (PyObject_GC_IsFinalized((PyObject *)self))

    return;

  PyObject *error_type,

      *error_value, *error_traceback;

  PyErr_Fetch(&error_type, &error_value, &error_traceback);

  PyObject_GC_UnTrack(self);

  Py_TYPE(self)->tp_clear((PyObject *)self);

  PyObject_GC_Del(self);

  PyErr_Restore(error_type, error_value, error_traceback);

}

static int Custom_clear(MyObject *self)

{

  printf("clear called\n");

  Py_CLEAR(self->myAttr);

  return 0;

}

static int Custom_traverse(MyObject *self, visitproc visit, void *arg)

{

  printf("traverse called\n");

  Py_VISIT(self->myAttr);

  return 0;

}

static int Custom_init(MyObject *self, PyObject *args, PyObject *kwds)

{

  self->myVal = 0;

  self->myAttr = Py_None;

  Py_XINCREF(Py_None);

  return 0;

}

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0, "MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyType_Slot mySlots[] = {

    {Py_tp_doc, "My Custom object"},

    {Py_tp_members, myMemberdef},

    {Py_tp_methods, myMethodDef},

    {Py_tp_clear, (inquiry)Custom_clear},

    {Py_tp_traverse, (traverseproc)Custom_traverse},

    {Py_tp_dealloc, (destructor)Custom_dealloc},

    {Py_tp_finalize,(destructor)Custom_finalizer},

    {0, NULL}};

PyType_Spec mySpec = {

    "example.myObject",

    sizeof(MyObject),

    0,

    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,

    mySlots};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  PyTypeObject *MyType1 = (PyTypeObject *)PyType_FromSpec(&mySpec);

  PyModule_AddObject(m, "MyClass", (PyObject *)MyType1);

  return m;

}

test.py

import example
import gc

myInst1=example.MyClass()
print(gc.is_tracked(myInst1))
#myInst1.MyAttr=myInst1
myInst1=None
print(gc.get_count())
gc.collect()
print(gc.get_count())

example.MyClass.myNewVar=43
print(example.MyClass.myNewVar)

Page 209

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyUnicodeObject str;

  int myVal;

  PyObject *myAttr;

} MyObject;

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0, "MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  MyType1.tp_base = &PyUnicode_Type;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
myInst1=example.MyClass("Hello")
print(len(myInst1))
myInst1.MyVar=42
print(myInst1.MyVar)
myInst1.MyMethod()
print("myInst=",myInst1)

Page 211

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyListObject list;

  int myVal;

  PyObject *myAttr;

} MyObject;

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0, "MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  MyType1.tp_base = &PyList_Type;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
myInst1=example.MyClass(["brian","spam",42])
print(myInst1)
print(len(myInst1))

Page 213

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"

typedef struct

{

  PyListObject list;

  int myVal;

  PyObject *myAttr;

} MyObject;

static PyObject *myFunc(MyObject *self, PyObject *args)

{

  printf("%d\n", self->myVal);

  printf("hello world\n");

  Py_RETURN_NONE;

};

static int Custom_init(MyObject *self, PyObject *args, PyObject *kwds)

{

  int res = Py_TYPE(self)->tp_base->tp_init((PyObject *)self, args, kwds);

  self->myVal = PyList_Size((PyObject *)self);

  return 0;

}

static void Custom_dealloc(MyObject *self)

{

  printf("destructor called\n");

  PyObject *error_type, *error_value, *error_traceback;

  PyErr_Fetch(&error_type, &error_value, &error_traceback);

  Py_TYPE(self)->tp_clear((PyObject *)self);

  Py_TYPE(self)->tp_base->tp_dealloc((PyObject *)self);

  PyErr_Restore(error_type, error_value, error_traceback);

}

static int Custom_clear(MyObject *self)

{

  printf("clear called\n");

  Py_CLEAR(self->myAttr);

  return 0;

}

static int Custom_traverse(MyObject *self, visitproc visit, void *arg)

{

  printf("traverse called\n");

  Py_VISIT(self->myAttr);

  PyList_Type.tp_traverse((PyObject *)self, visit, arg);

  return 0;

}

static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {"MyAttr", T_OBJECT_EX, offsetof(MyObject, myAttr), 0, "MyInstandeAttr"},

    {NULL}};

static PyMethodDef myMethodDef[] = {

    {"MyMethod", (PyCFunction)myFunc, METH_VARARGS, "the doc string"},

    {NULL}};

static PyTypeObject MyType1 = {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_members = myMemberdef,

    .tp_methods = myMethodDef,

    .tp_init = (initproc)Custom_init,

    .tp_clear = (inquiry)Custom_clear,

    .tp_traverse = (traverseproc)Custom_traverse,

    .tp_dealloc = (destructor)Custom_dealloc,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  MyType1.tp_base = &PyList_Type;

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
myInst1=example.MyClass(["brian","spam",42])
print(myInst1)
print(len(myInst1))
print(myInst1.MyVar)

Page 216

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <stddef.h>

#include "structmember.h"



static PyObject *myFactory(PyObject *self, PyObject *args)

{

  args = Py_BuildValue("()");

  PyObject *result = PyObject_Call((PyObject *)self, args, NULL);

  return result;

}

static PyMethodDef myFactory_def = {

    "myFactory",

    (PyCFunction)myFactory,

    METH_FASTCALL | METH_KEYWORDS,

    "the doc string"};

typedef struct

{

  PyObject_HEAD

  int myVal;

} MyObject;

static int Custom_init(MyObject *self, PyObject *args, PyObject *kwds)

{

  self->myVal = 0;

  return 0;

};



static PyMemberDef myMemberdef[] = {

    {"MyVar", T_INT, offsetof(MyObject, myVal), 0, "MyInstanceAttr"},

    {NULL}};



static PyTypeObject MyType1= {

    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)

                   .tp_name = "example.myObject",

    .tp_doc = PyDoc_STR("My Custom object"),

    .tp_flags = Py_TPFLAGS_DEFAULT,

    .tp_basicsize = sizeof(MyObject),

    .tp_itemsize = 0,

    .tp_new = PyType_GenericNew,

    .tp_init = (initproc)Custom_init,

    .tp_members = myMemberdef,

};

static struct PyModuleDef myModule = {

    PyModuleDef_HEAD_INIT,

    "example",

    "C library to test API",

    -1,

    NULL};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  PyObject *myPyFactory = PyCFunction_New(&myFactory_def,(PyObject*) &MyType1);

  PyModule_AddObject(m, "myFactory", myPyFactory);

  int res = PyType_Ready(&MyType1);

  PyModule_AddObject(m, "MyClass", (PyObject *)&MyType1);

  return m;

}

test.py

import example
myInst=example.myFactory()
print(myInst)
print(myInst.MyVar)
myInst.MyVar=42
print(myInst.MyVar)

Page 217

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *call(PyObject *self, PyObject *args)

{

  PyObject *math = PyImport_AddModule("math");

  PyObject *mathdict = PyModule_GetDict(math);

  PyObject *myFunction = PyDict_GetItemString(mathdict, "sqrt");

  args = Py_BuildValue("(I)", 2);

  PyObject *result = PyObject_Call(myFunction, args, NULL);

  return result;

}



static PyObject *object1(PyObject *self, PyObject *args)

{

  PyObject *main = PyImport_AddModule("__main__");

  PyObject *maindict = PyModule_GetDict(main);

  PyObject *myclass = PyDict_GetItemString(maindict, "myClass");

  args = Py_BuildValue("()");

  PyObject *result = PyObject_Call(myclass, args, NULL);

  PyObject *newValue = PyLong_FromLong(43);

  PyObject_SetAttrString(result, "myAttribute1", newValue);

  return result;

}

static PyMethodDef AddMethods[] = {

    {"call", call, METH_VARARGS, "an example"},

    {"object1", object1, METH_VARARGS, "an example"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef myModule = {

  PyModuleDef_HEAD_INIT,

  "example",                              

  "C library to test API",  

  -1,                                  

  AddMethods                          

};

PyMODINIT_FUNC PyInit_example(void)

{

  PyObject *m = PyModule_Create(&myModule);

  if (m == NULL)

    return NULL;

  return m;

}

test.py

import example

import math

class myClass:

    myAttribute1=0

print(example.call())

inst=example.object1()

print(inst)

print(inst.myAttribute1)


Page 226

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#if defined(_WIN32) || defined(_WIN64)

#define SCALE 1000

#else

#define SCALE 1

#endif

static PyObject *Pi(PyObject *self, PyObject *args)

{

     int m, n;

     double pi, s;

     if (!PyArg_ParseTuple(args, "ii", &m, &n))

          return NULL;

     Py_BEGIN_ALLOW_THREADS

     pi = 0;

     for (int k = m; k < n; k++)

     {

          s = 1;

          if (k % 2 == 0)

               s = -1;

          pi = pi + s / (2 * k - 1);

     }

     sleep(5 * SCALE);

     Py_END_ALLOW_THREADS

     return PyFloat_FromDouble(4 * pi);

}

static PyMethodDef AddMethods[] = {

    {"myPi", (PyCFunction)Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

     return PyModule_Create(&addmodule);

}

 test.py

import Pi

import time

import concurrent.futures

N=10000000

with concurrent.futures.ThreadPoolExecutor() as executor:

    t1=time.perf_counter()    

    f1 = executor.submit(Pi.myPi,1,N)

    t2=time.perf_counter()

    print("do some additional work")

    print("waiting for result")

    print(f1.result())

    print((t2-t1)*1000)

Page 227 LINUX VERSION

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

typedef struct

{

     int m;

     int n;

} range;

static pthread_mutex_t mutex;

static double PiShared = 0;

void *PartPi(void *args)

{

     range *range1 = (range *)args;

     double pi, s;

     int m = range1->m;

     int n = range1->n;

     pi = 0;

     for (int k = m; k < n; k++)

     {

          s = 1;

          if (k % 2 == 0)

               s = -1;

          pi = pi + s / (2 * k - 1);

     }

     pthread_mutex_lock(&mutex);

     PiShared += pi;

     pthread_mutex_unlock(&mutex);

     return NULL;

}

static PyObject *Pi(PyObject *self, PyObject *args)

{

     int m, n;

     if (!PyArg_ParseTuple(args, "ii", &m, &n))

          return NULL;

     Py_BEGIN_ALLOW_THREADS

         range range1 = {m, n / 2};

     range range2 = {n / 2 + 1, n};

     int threadId;

     pthread_mutex_init(&mutex, NULL);

     pthread_t thread1, thread2;

     pthread_create(&thread1, NULL, PartPi, &range1);

     pthread_create(&thread2, NULL, PartPi, &range2);

     pthread_join(thread1, NULL);

     pthread_join(thread2, NULL);

     Py_END_ALLOW_THREADS return PyFloat_FromDouble(4 * PiShared);

}

static PyMethodDef AddMethods[] = {

    {"myPi", (PyCFunction)Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

     return PyModule_Create(&addmodule);

}

Page 229 WINDOWS VERSION

example.c

 

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <Windows.h>

typedef struct

{

    int m;

    int n;

} range;

static int *Mutex;

static double PiShared = 0;

int PartPi(void *args)

{

    range *range1 = (range *)args;

    double pi, s;

    int m = range1->m;

    int n = range1->n;

    pi = 0;

    for (int k = m; k < n; k++)

    {

        s = 1;

        if (k % 2 == 0)

            s = -1;

        pi = pi + s / (2 * k - 1);

    }

    WaitForSingleObject(Mutex, INFINITE);

    PiShared += pi;

    ReleaseMutex(Mutex);

    return 0;

}

static PyObject *Pi(PyObject *self, PyObject *args)

{

    int m, n;

    int *handles[2];

    if (!PyArg_ParseTuple(args, "ii", &m, &n))

        return NULL;

    Py_BEGIN_ALLOW_THREADS

        range range1 = {m, n / 2};

    range range2 = {n / 2 + 1, n};

    int threadId;

    Mutex = CreateMutex(NULL, FALSE, NULL);

    handles[0] = CreateThread(NULL, 0, PartPi, (void *)&range1, 0, &threadId);

    handles[1] = CreateThread(NULL, 0, PartPi, (void *)&range2, 0, &threadId);

    WaitForMultipleObjects(2, handles, TRUE, INFINITE);

    Py_END_ALLOW_THREADS return PyFloat_FromDouble(4 * PiShared);

}

static PyMethodDef AddMethods[] = {

    {"myPi", (PyCFunction)Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

    PyObject *m = PyModule_Create(&addmodule);

    if (m == NULL)

        return NULL;

    return m;

}

 

 test.py

import Pi

import time

import concurrent.futures

N=10000000

with concurrent.futures.ThreadPoolExecutor() as executor:

    t1=time.perf_counter()    

    f1 = executor.submit(Pi.myPi,1,N)

    t2=time.perf_counter()

    print("do some additional work")

    print("waiting for result")

    print(f1.result())

    print((t2-t1)*1000)

Page 231 LINUX VERSION

example.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>

typedef struct

{

     int m;

     int n;

} range;

static pthread_mutex_t mutex;

static double PiShared = 0;

void *PartPi(void *args)

{

     range *range1 = (range *)args;

     double pi, s;

     int m = range1->m;

     int n = range1->n;

     pi = 0;

     for (int k = m; k < n; k++)

     {

          s = 1;

          if (k % 2 == 0)

               s = -1;

          pi = pi + s / (2 * k - 1);

     }

     pthread_mutex_lock(&mutex);

     PiShared += pi;

     pthread_mutex_unlock(&mutex);

     PyGILState_STATE gstate = PyGILState_Ensure();

     PyObject *pimod = PyImport_AddModule("Pi");

     PyObject *myVal = PyObject_GetAttrString(pimod, "myValue");

     PyObject *myOne = PyLong_FromLong(1);

     PyObject *myInc = PyNumber_Add(myVal, myOne);

     int res = PyObject_SetAttrString((PyObject *)pimod, "myValue", myInc);

     PyGILState_Release(gstate);

     return NULL;

}

static PyObject *Pi(PyObject *self, PyObject *args)

{

     int m, n;

     if (!PyArg_ParseTuple(args, "ii", &m, &n))

          return NULL;

     Py_BEGIN_ALLOW_THREADS

         range range1 = {m, n / 2};

     range range2 = {n / 2 + 1, n};

     pthread_mutex_init(&mutex, NULL);

     pthread_t thread1, thread2;

     pthread_create(&thread1, NULL, PartPi, &range1);

     pthread_create(&thread2, NULL, PartPi, &range2);

     pthread_join(thread1, NULL);

     pthread_join(thread2, NULL);

     Py_END_ALLOW_THREADS return PyFloat_FromDouble(4 * PiShared);

}

static PyMethodDef AddMethods[] = {

    {"myPi", (PyCFunction)Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

     PyObject *m = PyModule_Create(&addmodule);

     if (m == NULL)

          return NULL;

     PyObject *myValue = PyLong_FromLong(42);

     PyModule_AddObject(m, "myValue", myValue);

     return m;

}

Page 233 WINDOWS VERSION

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <Windows.h>

typedef struct

{

    int m;

    int n;

} range;

static int *Mutex;

static double PiShared = 0;

int PartPi(void *args)

{

    range *range1 = (range *)args;

    double pi, s;

    int m = range1->m;

    int n = range1->n;

    pi = 0;

    for (int k = m; k < n; k++)

    {

        s = 1;

        if (k % 2 == 0)

            s = -1;

        pi = pi + s / (2 * k - 1);

    }

    WaitForSingleObject(Mutex, INFINITE);

    PiShared += pi;

    ReleaseMutex(Mutex);

    PyGILState_STATE gstate = PyGILState_Ensure();

    PyObject *pimod = PyImport_AddModule("Pi");

    PyObject *myVal = PyObject_GetAttrString(pimod, "myValue");

    PyObject *myOne = PyLong_FromLong(1);

    PyObject *myInc = PyNumber_Add(myVal, myOne);

    int res = PyObject_SetAttrString((PyObject *)pimod, "myValue", myInc);

    PyGILState_Release(gstate);

    return 0;

}

static PyObject *Pi(PyObject *self, PyObject *args)

{

    int m, n;

    int *handles[2];

    if (!PyArg_ParseTuple(args, "ii", &m, &n))

         return NULL;

    Py_BEGIN_ALLOW_THREADS

    range range1 = {m, n / 2};

    range range2 = {n / 2 + 1, n};

    int threadId;

    Mutex = CreateMutex(NULL, FALSE, NULL);

    handles[0] = CreateThread(NULL, 0, PartPi, (void *)&range1, 0, &threadId);

    handles[1] = CreateThread(NULL, 0, PartPi, (void *)&range2, 0, &threadId);

    WaitForMultipleObjects(2, handles, TRUE, INFINITE);

    Py_END_ALLOW_THREADS

    return PyFloat_FromDouble(4 * PiShared);

}

static PyMethodDef AddMethods[] = {

    {"myPi", (PyCFunction)Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

    PyObject *m = PyModule_Create(&addmodule);

    if (m == NULL)

        return NULL;

    PyObject *myValue = PyLong_FromLong(42);

    PyModule_AddObject(m, "myValue", myValue);

    return m;

}

test.py

import Pi

import time

import concurrent.futures

N=10000000

print("go")

with concurrent.futures.ThreadPoolExecutor() as executor:    

    t1=time.perf_counter()    

    f1 = executor.submit(Pi.myPi,1,N)

    print("do some additional work")

    print("waiting for result")

    r=f1.result()

    t2=time.perf_counter()

    print((t2-t1)*1000)

    print(r)

    print(Pi.myValue)

Page 238 LINUX VERSION

#define PY_SSIZE_T_CLEAN

#include <Python.h>

typedef struct

{

    int m;

    int n;

    double Pi;

    PyObject *cb;

}State;

int Ccb(void *args)

{

    State *state = (State *)args;

    printf("C callback called \n");

    PyObject *pi=Py_BuildValue("(f)",state->Pi);

    PyObject_CallObject((PyObject *)(state->cb), pi);

    free(state);

    return 0;

}

static void *ComputePi(void *args)

{

    State *state = (State *)args;

    double pi, s;

    pi = 0;

    for (int k = state->m; k < state->n; k++)

    {

        s = 1;

        if (k % 2 == 0)

            s = -1;

        pi = pi + s / (2 * k - 1);

    }  

    state->Pi=4*pi;

    int res = Py_AddPendingCall(Ccb, (void *)state);

    return NULL;

}

static PyObject *Pi(PyObject *self, PyObject *args)

{

    int m, n;

    PyObject *cb;

    if (!PyArg_ParseTuple(args, "iiO:myPi", &m, &n, &cb))

        return NULL;

    State *state=(State*)malloc(sizeof(State));

    state->m = m;

    state->n = n;

    state->cb = cb;

    state->Pi = 0;

    pthread_t thread1;

    pthread_create(&thread1, NULL, ComputePi, (void *)state);

    return PyLong_FromLong(0);

}

static PyMethodDef AddMethods[] = {

    {"myPi", (PyCFunction)Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

    PyObject *m = PyModule_Create(&addmodule);

    if (m == NULL)

        return NULL;    

    return m;

}

 

Page 238 WINDOWS VERSION

 

#define PY_SSIZE_T_CLEAN

#include <Python.h>

#include <Windows.h>

typedef struct

{

    int m;

    int n;

    double Pi;

    PyObject *cb;

}State;

int Ccb(void *args)

{

    State *state = (State *)args;

    printf("C callback called \n");

    PyObject *pi=Py_BuildValue("(f)",state->Pi);

    PyObject_CallObject((PyObject *)state->cb, pi);

    free(state);

    return 0;

}

static int ComputePi(void *args)

{

    State *state = (State *)args;

    double pi, s;

    pi = 0;

    for (int k = state->m; k < state->n; k++)

    {

        s = 1;

        if (k % 2 == 0)

            s = -1;

        pi = pi + s / (2 * k - 1);

    }  

    state->Pi=4*pi;

    int res = Py_AddPendingCall(Ccb, (void *)state);

    return 0;

}

static PyObject *Pi(PyObject *self, PyObject *args)

{

    int m, n;

    PyObject *cb;

    if (!PyArg_ParseTuple(args, "iiO:myPi", &m, &n, &cb))

        return NULL;

    State *state=(State*)malloc(sizeof(State));

    state->m = m;

    state->n = n;

    state->cb = cb;

    state->Pi = 0;

    int threadId;

    int *handle = CreateThread(NULL, 0, ComputePi, (void *)state, 0, &threadId);

    return PyLong_FromLong(0);

}

static PyMethodDef AddMethods[] = {

    {"myPi", (PyCFunction)Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

    PyObject *m = PyModule_Create(&addmodule);

    if (m == NULL)

        return NULL;    

    return m;

}

 test.py

import Pi

import time

def myCallback(pi):

    t2 = time.perf_counter()

    print((t2-t1)*1000)

    print("python callback")

    print(pi)

N = 10000000

t1 = time.perf_counter()    

Pi.myPi(1,N,myCallback)

print("do some additional work")

while True:

    time.sleep(0.00001)


 

 Page 244

main.c

#define PY_SSIZE_T_CLEAN

#include <Python.h>



int main(int argc, char *argv[])

{

      Py_Initialize();

      PyRun_SimpleString("from time import time,ctime\n"

                         "print('Today is', ctime(time()))\n");

      Py_FinalizeEx();    

  return 0;

}

 

 tasks.json WINDOWS

 Change user name

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: cl.exe build active file",

            "command": "cl.exe",

            "args": [

                "/Zi",

                "/EHsc",

                "/nologo",

                "/IC:/Users/mike.james/AppData/Local/Programs/Python/Python311/include",

                "/Fe${fileDirname}\\${fileBasenameNoExtension}.exe",

                "${file}",

                "/link /LIBPATH:C:/Users/mike.james/AppData/Local/Programs/Python/Python311/libs"

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$msCompile"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

 tasks.json LINUX

 

{

    "tasks": [

        {

            "type": "cppbuild",

            "label": "C/C++: gcc-10 build active file",

            "command": "/usr/bin/gcc-10",

            "args": [

                "-fdiagnostics-color=always",

                "-g",                

                "${file}",

                "-o",

                "${fileDirname}/${fileBasenameNoExtension}",

                "-I/usr/local/include/python3.11",

                "-L/usr/local/lib/python3.11/config-3.11-arm-linux-gnueabihf",

                "-L/usr/local/lib",

                "-Xlinker",

                "-export-dynamic",

                "-lpython3.11",

                "-lpthread",

                "-ldl",

                "-lutil",

                "-lm",

            ],

            "options": {

                "cwd": "${fileDirname}"

            },

            "problemMatcher": [

                "$gcc"

            ],

            "group": {

                "kind": "build",

                "isDefault": true

            },

            "detail": "Task generated by Debugger."

        }

    ],

    "version": "2.0.0"

}

Page 247

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *Pi(PyObject *self, PyObject *args)

{

  int m, n;

  double pi, s;

  if (!PyArg_ParseTuple(args, "ii", &m, &n))

    return NULL;

  pi = 0;

  for (int k = m; k < n; k++)

  {

    s = 1;

    if (k % 2 == 0)

      s = -1;

    pi = pi + s / (2 * k - 1);

  }

  return PyFloat_FromDouble(4 * pi);

};

static PyMethodDef AddMethods[] = {

    {"myPi", Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

  return PyModule_Create(&addmodule);

};

int main(int argc, char *argv[])

{

  PyImport_AppendInittab("Pi", &PyInit_Pi);

  Py_Initialize();

  PyRun_SimpleString("import Pi\n"

    "print(Pi.myPi(1,1000))\n");

  Py_FinalizeEx();

  return 0;

}

Page 248

#define PY_SSIZE_T_CLEAN

#include <Python.h>



int main(int argc, char *argv[])

{

  Py_Initialize();

  PyObject *math =PyImport_ImportModule("math");

  PyObject *mathdict = PyModule_GetDict(math);

  PyObject *myFunction = PyDict_GetItemString(mathdict, "sqrt");

  PyObject *args = Py_BuildValue("(I)", 2);

  PyObject *result = PyObject_Call(myFunction, args, NULL);

  double res=PyFloat_AS_DOUBLE(result);

  printf("%f\n",res);

  PyRun_SimpleString(

    "import math\n"

    "print(math.sqrt(2))\n");

  Py_FinalizeEx();

  return 0;

}

Page 249

#define PY_SSIZE_T_CLEAN

#include <Python.h>

int main(int argc, char *argv[])

{

  Py_Initialize();

  {

    PyObject *g = PyDict_New();

    PyObject *l = PyDict_New();

    PyDict_SetItemString(l, "X", PyLong_FromLong(2));

    PyDict_SetItemString(l, "Y", PyLong_FromLong(2));

    PyObject *pyResult = PyRun_String("X+Y", Py_eval_input, g, l);

    int Cresult = PyLong_AS_LONG(pyResult);

    printf("%d\n", Cresult);

  }

  {

    PyObject *g = PyDict_New();  

    PyObject *l = PyDict_New();

    PyObject *math = PyImport_ImportModule("math");

    PyDict_SetItemString(g, "math", math);

    PyObject *pyResult = PyRun_String("math.sqrt(2)", Py_eval_input, g, l);

    double res2 = PyFloat_AS_DOUBLE(pyResult);

    printf("%f\n", res2);

  }

  Py_FinalizeEx();

  return 0;

}

Page 250

#define PY_SSIZE_T_CLEAN

#include <Python.h>

static PyObject *Pi(PyObject *self, PyObject *args)

{

    int m, n;

    double pi, s;

    if (!PyArg_ParseTuple(args, "ii", &m, &n))

        return NULL;

    pi = 0;

    for (int k = m; k < n; k++)

    {

        s = 1;

        if (k % 2 == 0)

            s = -1;

        pi = pi + s / (2 * k - 1);

    }

    return PyFloat_FromDouble(4 * pi);

}

static PyMethodDef AddMethods[] = {

    {"myPi", Pi, METH_VARARGS, "Compute Pi"},

    {NULL, NULL, 0, NULL} // sentinel

};

static struct PyModuleDef addmodule = {

    PyModuleDef_HEAD_INIT,

    "Pi",

    "C library to compute Pi",

    -1,

    AddMethods};

PyMODINIT_FUNC PyInit_Pi(void)

{

    return PyModule_Create(&addmodule);

}

int main(int argc, char *argv[])

{

    PyImport_AppendInittab("Pi", &PyInit_Pi);

    Py_Initialize();

    PyObject *main = PyImport_AddModule("__main__");

    PyObject *mainDict = PyModule_GetDict(main);

    FILE *fp = fopen("Pi.py", "r");

    PyObject *l = PyDict_New();

    PyObject *result = PyRun_File(fp, "Pi.py", Py_file_input, mainDict, l);

    Py_FinalizeEx();

    return 0;

}

Pi,py

import Pi
import time
N=10000000
t1=time.perf_counter()
pi=Pi.myPi(1,N)
t2=time.perf_counter()
print((t2-t1)*1000)
print(pi)