Extending & Embedding Python Using C
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
#includestatic 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
}
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;
}
import example
myclass=example.MyClass
print(myclass)
print(myclass.__dict__)
Page 173
#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 gcmyInst1=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 gcmyInst1=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 gcmyInst1=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)
Programs
Raspberry Pi IoT in C Third Edition
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 a VS Code project.
Note: The VS Code task listings are in Appendix II.
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 - in particular remember to add the bcm2835 library and also any library references that may be needed. The majority of the programs also need to be run with root permissions.
All of the programs below were copy and pasted from working programs in the IDE.
If anything you consider important is missing or if you have any requests or comments contact me
This email address is being protected from spambots. You need JavaScript enabled to view it.
Chapter 2
Page 28
Chapter 3
Page 47
Chapter 4
Page 50
Page 62
Page 64
Page 65
Page 66
Page 67
Page 68
Chapter 6
Page 89
Page 90
Page 91
Page 92
Page 93
Page 94
Page 97
Page 99
Page 100
Chapter 7
Page 111
Page 114
Page 116
Chapter 8
Page 122
Page 126
Page 127
Page 128
Page 129
Page 132
Page 137
page 140
Chapter 9
Page 151
Page 152
Page 153
Page 155
Page 156
Page 158
Page 159
Page 160
Page 163
Page 164
Page 166
Page 168
Chapter 10
Page 184
Page 186
Page 188
Page 192
Chapter 11
Page 203
Chapter 13
Page 223
Chapter 14
Page 233
Chapter 15
Page 246
function only - needs a main program to call it
Chapter 16
Page 268
On a Pi 5 serial0 opens the debug port. If you want to use GPIO14 and 15 use /dev/ttyAMA0 or any UART you have enabled.
#include <unistd.h>
#include <fcntl.h>
Page 268
On a Pi 5 serial0 opens the debug port. If you want to use GPIO14 and 15 use /dev/ttyAMA0 or any UART you have enabled.
This loopback most likely wont work unless the serial port is already configured - see next program.
Page 278
On a Pi 5 serial0 opens the debug port. If you want to use GPIO14 and 15 use /dev/ttyAMA0 or any UART you have enabled.
Page 279
On a Pi 5 serial0 opens the debug port. If you want to use GPIO14 and 15 use /dev/ttyAMA0 or any UART you have enabled.
Page 281
On a Pi 5 serial0 opens the debug port. If you want to use GPIO14 and 15 use /dev/ttyAMA0 or any UART you have enabled.
Page 287
On a Pi 5 serial0 opens the debug port. If you want to use GPIO14 and 15 use /dev/ttyAMA0 or any UART you have enabled.
Chapter 17
Page 303
Chapter 18
Page 312
Chapter 19
Page 324
Page 326
Page 331
Chapter 20
Page 350
Page 355
Page 360
Page 362
Page 370
Chapter 21
Page 372
Page 378
Chapter 22
Page 395
Page 399
Page 402
Appendix I
Page 406
Page 407
Appendix II
All files have to be stored in the .vscode folder
settings,json (typical)
launch.json
c_cpp_properties.json for Mingw
tasks.json
"showReuseMessage": true,
}
},
{
"label": "copyARMheaders",
"type": "shell",
"command": "mkdir ${workspaceFolder}/include/;scp -r ${config:sshUser}@${config:sshEndpoint}:/usr/include ${workspaceFolder}/include/ ",
"problemMatcher": [],
"presentation": {
"showReuseMessage": true,
"clear": true
}
},
],
}
Raspberry Pi IoT In Python Using Linux Drivers
Second Edition
Programs
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 a NetBeans of VS Code project.
Note: The VS Code task listings are at the very end of this page.
The only downside is that you have to create a project to paste the code into.
To do this follow the instructionin the book-- in particular make sure you have added any libraries to the link step and are running as root if required.
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 41
Page 43
Page 53
Page 57
Page 57
Remember the need to change the chip number to "4" for a Pi 5.
Page 59
Remember the need to change the chip number to "4" for a Pi 5.
Page 67
Page 70
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 72
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 73
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 80
Remember to change the chip number from “0” to “4” if running on a Pi 5.
Page 81
Remember to change the chip number from “0” to “4” if running on a Pi 5.
Page 82
Remember to change the chip number from “0” to “4” if running on a Pi 5.
Page 783a
Don’t forget to change "0" to "4" if running on a Pi 5.
Page 83b
Don’t forget to change "0" to "4" if running on a Pi 5.
Page 84
Don’t forget to change "0" to "4" if running on a Pi 5.
Page 87
Don’t forget to change "0" to "4" if running on a Pi 5.
Page 88
Don’t forget to change "0" to "4" if running on a Pi 5.
Page 90
Page 100
Page 102
Page 123a
Remember to change "0" to "4" if you are running on a Pi 5.
Page 123b
Remember to change "0" to "4" if you are running on a Pi 5.
Page 127
Page 128
Page 130
Page 141
Page 151
Page 161
Page 181
Page 183
Page 187
Page 197
Page 200
Page 204
Page 212
Page 215
Page 229
Page 240
VSCODE TASKS
settings.json
which has to be customized to your IP, user name and folder:
tasks.json
Raspberry Pi IoT In C Using Linux Drivers
Second Edition
Programs
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 a NetBeans of VS Code project.
The only downside is that you have to create a project to paste the code into.
To do this follow the instructionin the book-- in particular make sure you have added any libraries to the link step and are running as root if required.
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 26
Page 44
Page 45
Page 54
Remember to change "0" to "4" if running on a Pi 5.
Page 55
Remember to change "0" to "4" if running on a Pi 5.
Page 56
Page 58
Remember to change chip number 0 to 4 if running on a Pi 5.
Page 60
Remember to change chip number 0 to 4 if running on a Pi 5.
Page 64
Remember to change chip number 0 to 4 if running on a Pi 5.
Page 66
Remember to change chip number 0 to 4 if running on a Pi 5.
Page 70
If you run this on a Pi 5 change gpiochip0 to gpiochip4.
Page 73
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 74
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 75
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 83
Page 84
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 85
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 86
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 87
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 88
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 92
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 93
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 97
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 100
Remember to change gpiochip0 to gpiochip4 if you are running on a Pi 5.
Page 110
Page 112
Page 133
Remember to change "0" to "4" if you are running on a Pi 5.
Page 134
Remember to change "0" to "4" if you are running on a Pi 5.
Page 137
Remember to change "0" to "4" if you are running on a Pi 5.
Page 139
Page 141 - full listing of finished program on Page 155
Page 167
Page 177
Page 197
Page 206
Page 219
Page 222
Page 227
Page 234
Page 248
Page 269
launch.json
tasks.json
c_cpp_properties.json for Mingw
Page 4 of 6