Skip to content

Commit f1e59df

Browse files
committed
Fixing C dependencies
1 parent dcf7aa0 commit f1e59df

12 files changed

Lines changed: 400 additions & 4 deletions

File tree

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
11
**/*.pyc
2+
__pycache__
3+
.mypy_cache
4+
lib
5+
bin
6+
include
7+
pyvenv.cfg
8+
*.egg-info
9+
*.so
10+
*.lib
11+
build
12+

example_code/item_095.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ def dot_product(a, b):
6565
import pathlib
6666

6767
run_py = pathlib.Path(__file__)
68-
tools_dir = run_py.parent
69-
root_dir = tools_dir.parent
70-
# TODO: Fix this for example code
71-
library_path = root_dir / "Ch11" / "my_library" / "my_library.lib"
68+
library_path = run_py.parent / "item_095" / "my_library" / "my_library.lib"
7269

7370
my_library = ctypes.cdll.LoadLibrary(library_path)
7471

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <stdio.h>
18+
#include "my_library.h"
19+
20+
double dot_product(int length, double* a, double* b) {
21+
double result = 0;
22+
for (int i = 0; i < length; i++) {
23+
result += a[i] * b[i];
24+
}
25+
return result;
26+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
extern double dot_product(int length, double* a, double* b);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <assert.h>
18+
#include <math.h>
19+
#include <stdio.h>
20+
#include "my_library.h"
21+
22+
23+
int main(int argc, char** argv) {
24+
{
25+
double a[] = {3, 4, 5};
26+
double b[] = {-1, 9, -2.5};
27+
double found = dot_product(3, a, b);
28+
double expected = 20.5;
29+
printf("Found %f, Expected %f\n", found, expected);
30+
assert(fabs(found - expected) < 0.01);
31+
}
32+
33+
{
34+
double a[] = {0, 0, 0};
35+
double b[] = {1, 1, 1};
36+
double found = dot_product(3, a, b);
37+
double expected = 0;
38+
printf("Found %f, Expected %f\n", found, expected);
39+
assert(fabs(found - expected) < 0.01);
40+
}
41+
42+
{
43+
double a[] = {-1, -1, -1};
44+
double b[] = {1, 1, 1};
45+
double found = dot_product(3, a, b);
46+
double expected = -3;
47+
printf("Found %f, Expected %f\n", found, expected);
48+
assert(fabs(found - expected) < 0.01);
49+
}
50+
51+
return 0;
52+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "my_extension.h"
18+
19+
PyObject *dot_product(PyObject *self, PyObject *args)
20+
{
21+
PyObject *left, *right;
22+
if (!PyArg_ParseTuple(args, "OO", &left, &right)) {
23+
return NULL;
24+
}
25+
if (!PyList_Check(left) || !PyList_Check(right)) {
26+
PyErr_SetString(PyExc_TypeError, "Both arguments must be lists");
27+
return NULL;
28+
}
29+
30+
Py_ssize_t left_length = PyList_Size(left);
31+
Py_ssize_t right_length = PyList_Size(right);
32+
if (left_length == -1 || right_length == -1) {
33+
return NULL;
34+
}
35+
if (left_length != right_length) {
36+
PyErr_SetString(PyExc_ValueError, "Lists must be the same length");
37+
return NULL;
38+
}
39+
40+
double result = 0;
41+
42+
for (Py_ssize_t i = 0; i < left_length; i++) {
43+
PyObject *left_item = PyList_GET_ITEM(left, i);
44+
PyObject *right_item = PyList_GET_ITEM(right, i);
45+
46+
double left_double = PyFloat_AsDouble(left_item);
47+
double right_double = PyFloat_AsDouble(right_item);
48+
if (PyErr_Occurred()) {
49+
return NULL;
50+
}
51+
52+
result += left_double * right_double;
53+
}
54+
55+
return PyFloat_FromDouble(result);
56+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "my_extension.h"
18+
19+
static PyMethodDef my_extension_methods[] = {
20+
{
21+
"dot_product",
22+
dot_product,
23+
METH_VARARGS,
24+
"Compute dot product",
25+
},
26+
{
27+
NULL,
28+
NULL,
29+
0,
30+
NULL,
31+
},
32+
};
33+
34+
static struct PyModuleDef my_extension = {
35+
PyModuleDef_HEAD_INIT,
36+
"my_extension",
37+
"My C-extension module",
38+
-1,
39+
my_extension_methods,
40+
};
41+
42+
PyMODINIT_FUNC
43+
PyInit_my_extension(void)
44+
{
45+
return PyModule_Create(&my_extension);
46+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#define PY_SSIZE_T_CLEAN
18+
#include <Python.h>
19+
20+
PyObject *dot_product(PyObject *self, PyObject *args);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "my_extension2.h"
18+
19+
PyObject *dot_product(PyObject *self, PyObject *args)
20+
{
21+
PyObject *left, *right;
22+
if (!PyArg_ParseTuple(args, "OO", &left, &right)) {
23+
return NULL;
24+
}
25+
PyObject *left_iter = PyObject_GetIter(left);
26+
if (left_iter == NULL) {
27+
return NULL;
28+
}
29+
PyObject *right_iter = PyObject_GetIter(right);
30+
if (right_iter == NULL) {
31+
Py_DECREF(left_iter);
32+
return NULL;
33+
}
34+
35+
PyObject *left_item = NULL;
36+
PyObject *right_item = NULL;
37+
PyObject *multiplied = NULL;
38+
PyObject *result = PyLong_FromLong(0);
39+
40+
while (1) {
41+
Py_CLEAR(left_item);
42+
Py_CLEAR(right_item);
43+
Py_CLEAR(multiplied);
44+
left_item = PyIter_Next(left_iter);
45+
right_item = PyIter_Next(right_iter);
46+
47+
if (left_item == NULL && right_item == NULL) {
48+
break;
49+
} else if (left_item == NULL || right_item == NULL) {
50+
PyErr_SetString(PyExc_ValueError, "Arguments had unequal length");
51+
break;
52+
}
53+
54+
multiplied = PyNumber_Multiply(left_item, right_item);
55+
if (multiplied == NULL) {
56+
break;
57+
}
58+
PyObject *added = PyNumber_Add(result, multiplied);
59+
if (added == NULL) {
60+
break;
61+
}
62+
Py_CLEAR(result);
63+
result = added;
64+
}
65+
66+
Py_CLEAR(left_item);
67+
Py_CLEAR(right_item);
68+
Py_CLEAR(multiplied);
69+
Py_DECREF(left_iter);
70+
Py_DECREF(right_iter);
71+
72+
if (PyErr_Occurred()) {
73+
Py_CLEAR(result);
74+
return NULL;
75+
}
76+
77+
return result;
78+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2014-2024 Brett Slatkin, Pearson Education Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "my_extension2.h"
18+
19+
static PyMethodDef my_extension2_methods[] = {
20+
{
21+
"dot_product",
22+
dot_product,
23+
METH_VARARGS,
24+
"Compute dot product",
25+
},
26+
{
27+
NULL,
28+
NULL,
29+
0,
30+
NULL,
31+
},
32+
};
33+
34+
static struct PyModuleDef my_extension2 = {
35+
PyModuleDef_HEAD_INIT,
36+
"my_extension2",
37+
"My second C-extension module",
38+
-1,
39+
my_extension2_methods,
40+
};
41+
42+
PyMODINIT_FUNC
43+
PyInit_my_extension2(void)
44+
{
45+
return PyModule_Create(&my_extension2);
46+
}

0 commit comments

Comments
 (0)