Skip to content

Commit bbe7f8e

Browse files
author
Ailing Zhang
committed
Init example with ctypes and pybind11 and cpython
0 parents  commit bbe7f8e

File tree

11 files changed

+179
-0
lines changed

11 files changed

+179
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
build/*
2+
__pycache__/*
3+
*.so
4+
*.egg-info

.gitmodules

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
cmake_minimum_required(VERSION 3.4...3.18)
2+
project(sum)
3+
4+
# The following has been moved to setup.py
5+
# To enable this you'll need a pybind11 submodule
6+
#add_subdirectory(pybind11)
7+
#pybind11_add_module(sum_from_pybind11 src/sum_pybind11.cpp)
8+
#target_include_directories(sum_from_pybind11 PRIVATE src/)
9+
#target_compile_definitions(sum_from_pybind11 PRIVATE VERSION_INFO=0.1)
10+
add_library(sum_from_ctypes MODULE src/sum.c)
11+

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Compile for ctypes demo
2+
I didn't bother writing a proper `build_ext` for this so manual copy is required.
3+
4+
```
5+
mkdir build
6+
cd build
7+
cmake .. && make
8+
cp *.so ../
9+
```
10+
11+
# Compile pybind11 & cpython demo
12+
```
13+
python setup.py build && pip install -e .
14+
```
15+
16+
# Run
17+
18+
```
19+
python main.py
20+
```
21+
22+
# References
23+
- https://en.wikibooks.org/wiki/Python_Programming/Extending_with_C
24+
- https://github.com/pybind/python_example
25+
- https://pgi-jcns.fz-juelich.de/portal/pages/using-c-from-python.html
26+
- https://gist.github.com/physacco/2e1b52415f3a964ad2a542a99bebed8f
27+
- https://scipy-lectures.org/advanced/interfacing_with_c/interfacing_with_c.html#id1
28+
- https://stackoverflow.com/questions/22458298/extending-python-with-c-pass-a-list-to-pyarg-parsetuple

main.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import sum_from_ctypes
2+
import sum_from_pybind11
3+
import sum_from_cpython
4+
import time
5+
6+
N = 50
7+
8+
def timed_run(func, name):
9+
a = [1] * 100
10+
start = time.time()
11+
for _ in range(N):
12+
func(a)
13+
print(f'{name} took {(time.time() - start) / N}s')
14+
15+
16+
timed_run(sum_from_ctypes.my_sum, 'ctypes')
17+
timed_run(sum_from_pybind11.my_sum, 'pybind')
18+
timed_run(sum_from_cpython.my_sum, 'cpython')
19+

setup.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# DO NOT reorder these imports due to monkey-patch
2+
from pybind11.setup_helpers import Pybind11Extension
3+
from distutils.core import setup, Extension
4+
5+
cpython_mod = Extension('sum_from_cpython', sources = ['src/sum_cpython.c'])
6+
pybind_mod = Pybind11Extension('sum_from_pybind11', sources = ['src/sum_pybind11.cpp'])
7+
8+
setup (name = 'demo',
9+
version = '0.0',
10+
description = 'This is a demo package',
11+
ext_modules = [cpython_mod, pybind_mod])

src/sum.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "sum.h"

src/sum.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <stdio.h>
2+
#include <time.h>
3+
#include <sys/time.h>
4+
5+
int my_sum(int num_numbers, int *numbers) {
6+
#if 0
7+
long start, end;
8+
struct timeval timecheck;
9+
gettimeofday(&timecheck, NULL);
10+
start = (long)timecheck.tv_sec * 1000 * 1000 + (long)timecheck.tv_usec;
11+
#endif
12+
int i;
13+
int sum = 0;
14+
for (i = 0; i < num_numbers; i++) {
15+
sum += numbers[i];
16+
}
17+
#if 0
18+
gettimeofday(&timecheck, NULL);
19+
end = (long)timecheck.tv_sec * 1000 * 1000 + (long)timecheck.tv_usec;
20+
printf("%ld us elapsed\n", (end - start));
21+
#endif
22+
return sum;
23+
}

src/sum_cpython.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <stdio.h>
2+
#include <Python.h>
3+
4+
// Module method definitions
5+
static PyObject* my_sum_from_cpython(PyObject *self, PyObject *args) {
6+
PyObject *pList;
7+
PyObject *pItem;
8+
Py_ssize_t n;
9+
int i;
10+
if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &pList)) {
11+
PyErr_SetString(PyExc_TypeError, "parameter must be a list");
12+
return NULL;
13+
}
14+
n = PyList_Size(pList);
15+
long sum = 0;
16+
for (i = 0; i < n; i++) {
17+
pItem = PyList_GetItem(pList, i);
18+
if (!PyLong_Check(pItem)) {
19+
return NULL;
20+
}
21+
sum += PyLong_AsLong(pItem);
22+
}
23+
return Py_BuildValue("l", sum);
24+
}
25+
// Method definition object for this extension, these argumens mean:
26+
// ml_name: The name of the method
27+
// ml_meth: Function pointer to the method implementation
28+
// ml_flags: Flags indicating special features of this method, such as
29+
// accepting arguments, accepting keyword arguments, being a
30+
// class method, or being a static method of a class.
31+
// ml_doc: Contents of this method's docstring
32+
static PyMethodDef sum_from_cpython_methods[] = {
33+
{
34+
"my_sum", my_sum_from_cpython, METH_VARARGS, ""
35+
},
36+
{NULL, NULL, 0, NULL}
37+
};
38+
39+
// Module definition
40+
// The arguments of this structure tell Python what to call your extension,
41+
// what it's methods are and where to look for it's method definitions
42+
static struct PyModuleDef sum_from_cpython_definition = {
43+
PyModuleDef_HEAD_INIT,
44+
"sum_from_cpython",
45+
"A Python module that prints 'sum_from_cpython world' from C code.",
46+
-1,
47+
sum_from_cpython_methods
48+
};
49+
50+
// Module initialization
51+
// Python calls this function when importing your extension. It is important
52+
// that this function is named PyInit_[[your_module_name]] exactly, and matches
53+
// the name keyword argument in setup.py's setup() call.
54+
PyMODINIT_FUNC PyInit_sum_from_cpython(void) {
55+
Py_Initialize();
56+
return PyModule_Create(&sum_from_cpython_definition);
57+
}

src/sum_pybind11.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <pybind11/pybind11.h>
2+
#include <pybind11/stl.h>
3+
4+
#include "sum.h"
5+
6+
namespace py = pybind11;
7+
8+
PYBIND11_MODULE(sum_from_pybind11, m) {
9+
m.def("my_sum", [](std::vector<int>& data) {
10+
int sum = my_sum(data.size(), data.data());
11+
return sum;
12+
}, "");
13+
}

0 commit comments

Comments
 (0)