Skip to content

Instantly share code, notes, and snippets.

@deeTEEcee
Created October 17, 2022 00:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deeTEEcee/76c471bb6020d50970df7a9697b11130 to your computer and use it in GitHub Desktop.
Save deeTEEcee/76c471bb6020d50970df7a9697b11130 to your computer and use it in GitHub Desktop.
Python Integration w/ C

Two things we can do with C and Python integration.

  1. C Extensions for Python

    In other words, we can write python methods in pure C.

  2. Embedding Python a

The reasons for doing #1 are obvious because we can make speed improvements. For #2, it is due to transporting Python libraries over to C.

Compilation

Compilation is a bit more challenging because we have to do something like:

gcc -I /usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/include/python3.7m hello.c -o hello

However, we can actually utilize a hidden utility python seems to be hiding from us called "python-config." As long as you can find where Python is installed, you can find the necessary directories. With python-config, you can do this instead:

# Double dollar sign is used to differentiate syntax usage if you use this in a Makefile 
gcc $$(/usr/local/opt/python@3.7/Frameworks/Python.framework/Versions/3.7/bin/python3.7-config --cflags) hello.c -o hello
#./hello

The embedded version requires further options so we have to add --embed and --ldflags to make things easier.

gcc $$(/opt/homebrew/Cellar/python@3.8/3.8.15/Frameworks/Python.framework/Versions/3.8/bin/python3.8-config --cflags --ldflags --embed) embedded.c -o embedded
./embedded
// Example C extension which ends up being a Python method you can call.
#include <Python.h>
int Cfib(int n) {
if (n < 2)
return n;
else
return Cfib(n - 1) + Cfib(n - 2);
}
static PyObject* fib(PyObject* self, PyObject* args) {
int n;
if (!PyArg_ParseTuple(args, "i", &n))
return NULL;
return Py_BuildValue("i", Cfib(n));
}
static PyMethodDef myMethods[] = {
{"fib", fib, METH_VARARGS, "Calculates the fibonacci numbers"},
{NULL, NULL, 0, NULL} // wat
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"cmodule", /* m_name */
"Fib Module", /* m_doc */
-1, /* m_size */
myMethods, /* m_methods */
// NULL, /* m_reload */
// NULL, /* m_traverse */
// NULL, /* m_clear*/
// NULL, /* m_free */
};
PyMODINIT_FUNC PyInit_cmodule(void)
{
return PyModule_Create(&module);
}
int main() {
// printf() displays the string inside quotation
printf("Hello, Fibonacci World!\n");
return 0;
}
// Example Python embedded inside a C/C++ file.
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment