Skip to content

Commit 17e09bf

Browse files
authored
Fix #789: Remove cyclical import between driver and _lib.utils (#865)
* Move param_packer.cpp -> param_packer.h * Fix #789: Remove cyclical import between driver and _lib.utils * Add a test for cyclical imports * Only raise on cuda.bindings modules
1 parent b003a92 commit 17e09bf

15 files changed

Lines changed: 530 additions & 473 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ __pycache__/
1616
cache_driver
1717
cache_runtime
1818
cache_nvrtc
19+
cuda_bindings/cuda/bindings/_lib/utils.pxi
1920

2021
# CUDA Python specific (auto-generated)
2122
cuda_bindings/cuda/bindings/_bindings/cydriver.pxd

cuda_bindings/cuda/bindings/_lib/param_packer.cpp

Lines changed: 0 additions & 159 deletions
This file was deleted.
Lines changed: 143 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,152 @@
11
// SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
// SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
3-
//
3+
44
// Please refer to the NVIDIA end user license agreement (EULA) associated
55
// with this source code for terms and conditions that govern your use of
66
// this software. Any use, reproduction, disclosure, or distribution of
77
// this software and related documentation outside the terms of the EULA
88
// is strictly prohibited.
9-
#pragma once
9+
1010
#include <Python.h>
1111

12-
int feed(void* ptr, PyObject* value, PyObject* type);
12+
#include <map>
13+
#include <functional>
14+
#include <stdexcept>
15+
#include <string>
16+
17+
static PyObject* ctypes_module = nullptr;
18+
19+
static PyTypeObject* ctypes_c_char = nullptr;
20+
static PyTypeObject* ctypes_c_bool = nullptr;
21+
static PyTypeObject* ctypes_c_wchar = nullptr;
22+
static PyTypeObject* ctypes_c_byte = nullptr;
23+
static PyTypeObject* ctypes_c_ubyte = nullptr;
24+
static PyTypeObject* ctypes_c_short = nullptr;
25+
static PyTypeObject* ctypes_c_ushort = nullptr;
26+
static PyTypeObject* ctypes_c_int = nullptr;
27+
static PyTypeObject* ctypes_c_uint = nullptr;
28+
static PyTypeObject* ctypes_c_long = nullptr;
29+
static PyTypeObject* ctypes_c_ulong = nullptr;
30+
static PyTypeObject* ctypes_c_longlong = nullptr;
31+
static PyTypeObject* ctypes_c_ulonglong = nullptr;
32+
static PyTypeObject* ctypes_c_size_t = nullptr;
33+
static PyTypeObject* ctypes_c_float = nullptr;
34+
static PyTypeObject* ctypes_c_double = nullptr;
35+
static PyTypeObject* ctypes_c_void_p = nullptr;
36+
37+
static void fetch_ctypes()
38+
{
39+
ctypes_module = PyImport_ImportModule("ctypes");
40+
if (ctypes_module == nullptr)
41+
throw std::runtime_error("Cannot import ctypes module");
42+
// get method addressof
43+
PyObject* ctypes_dict = PyModule_GetDict(ctypes_module);
44+
if (ctypes_dict == nullptr)
45+
throw std::runtime_error(std::string("FAILURE @ ") + std::string(__FILE__) + " : " + std::to_string(__LINE__));
46+
// supportedtypes
47+
ctypes_c_char = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_char");
48+
ctypes_c_bool = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_bool");
49+
ctypes_c_wchar = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_wchar");
50+
ctypes_c_byte = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_byte");
51+
ctypes_c_ubyte = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_ubyte");
52+
ctypes_c_short = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_short");
53+
ctypes_c_ushort = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_ushort");
54+
ctypes_c_int = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_int");
55+
ctypes_c_uint = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_uint");
56+
ctypes_c_long = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_long");
57+
ctypes_c_ulong = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_ulong");
58+
ctypes_c_longlong = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_longlong");
59+
ctypes_c_ulonglong = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_ulonglong");
60+
ctypes_c_size_t = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_size_t");
61+
ctypes_c_float = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_float");
62+
ctypes_c_double = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_double");
63+
ctypes_c_void_p = (PyTypeObject*) PyDict_GetItemString(ctypes_dict, "c_void_p"); // == c_voidp
64+
}
65+
66+
67+
// (target type, source type)
68+
static std::map<std::pair<PyTypeObject*,PyTypeObject*>, std::function<int(void*, PyObject*)>> m_feeders;
69+
70+
static void populate_feeders(PyTypeObject* target_t, PyTypeObject* source_t)
71+
{
72+
if (target_t == ctypes_c_int)
73+
{
74+
if (source_t == &PyLong_Type)
75+
{
76+
m_feeders[{target_t,source_t}] = [](void* ptr, PyObject* value) -> int
77+
{
78+
*((int*)ptr) = (int)PyLong_AsLong(value);
79+
return sizeof(int);
80+
};
81+
return;
82+
}
83+
} else if (target_t == ctypes_c_bool) {
84+
if (source_t == &PyBool_Type)
85+
{
86+
m_feeders[{target_t,source_t}] = [](void* ptr, PyObject* value) -> int
87+
{
88+
*((bool*)ptr) = (value == Py_True);
89+
return sizeof(bool);
90+
};
91+
return;
92+
}
93+
} else if (target_t == ctypes_c_byte) {
94+
if (source_t == &PyLong_Type)
95+
{
96+
m_feeders[{target_t,source_t}] = [](void* ptr, PyObject* value) -> int
97+
{
98+
*((int8_t*)ptr) = (int8_t)PyLong_AsLong(value);
99+
return sizeof(int8_t);
100+
};
101+
return;
102+
}
103+
} else if (target_t == ctypes_c_double) {
104+
if (source_t == &PyFloat_Type)
105+
{
106+
m_feeders[{target_t,source_t}] = [](void* ptr, PyObject* value) -> int
107+
{
108+
*((double*)ptr) = (double)PyFloat_AsDouble(value);
109+
return sizeof(double);
110+
};
111+
return;
112+
}
113+
} else if (target_t == ctypes_c_float) {
114+
if (source_t == &PyFloat_Type)
115+
{
116+
m_feeders[{target_t,source_t}] = [](void* ptr, PyObject* value) -> int
117+
{
118+
*((float*)ptr) = (float)PyFloat_AsDouble(value);
119+
return sizeof(float);
120+
};
121+
return;
122+
}
123+
} else if (target_t == ctypes_c_longlong) {
124+
if (source_t == &PyLong_Type)
125+
{
126+
m_feeders[{target_t,source_t}] = [](void* ptr, PyObject* value) -> int
127+
{
128+
*((long long*)ptr) = (long long)PyLong_AsLongLong(value);
129+
return sizeof(long long);
130+
};
131+
return;
132+
}
133+
}
134+
}
135+
136+
static int feed(void* ptr, PyObject* value, PyObject* type)
137+
{
138+
PyTypeObject* pto = (PyTypeObject*)type;
139+
if (ctypes_c_int == nullptr)
140+
fetch_ctypes();
141+
auto found = m_feeders.find({pto,value->ob_type});
142+
if (found == m_feeders.end())
143+
{
144+
populate_feeders(pto, value->ob_type);
145+
found = m_feeders.find({pto,value->ob_type});
146+
}
147+
if (found != m_feeders.end())
148+
{
149+
return found->second(ptr, value);
150+
}
151+
return 0;
152+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
33

4+
# Include "param_packer.h" so its contents get compiled into every
5+
# Cython extension module that depends on param_packer.pxd.
46
cdef extern from "param_packer.h":
57
int feed(void* ptr, object o, object ct)

0 commit comments

Comments
 (0)