Skip to content

Commit 9b05c59

Browse files
committed
Add test for resolving caster in a namespace
1 parent cb9b380 commit 9b05c59

File tree

7 files changed

+96
-3
lines changed

7 files changed

+96
-3
lines changed

src/semiwrap/cmd_resolve_casters.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,20 @@ def _update_all_casters(type_caster_cfg: pathlib.Path, all_casters: CastersData)
2424
)
2525

2626
for typ in item.types:
27+
td = TypeData(
28+
header=header, typename=typ, default_arg_cast=item.default_arg_cast
29+
)
30+
2731
if typ not in all_casters:
28-
all_casters[typ] = TypeData(
29-
header=header, typename=typ, default_arg_cast=item.default_arg_cast
30-
)
32+
all_casters[typ] = td
33+
34+
# in addition to the type, add a non-namespaced version too
35+
# - in theory this could cause conflicts, but in practice its useful
36+
# - this could be solved by making the parser resolve namespaces, but
37+
# that has downsides too
38+
ntyp = typ.split("::")[-1]
39+
if ntyp not in all_casters:
40+
all_casters[ntyp] = td
3141

3242

3343
def main():

tests/cpp/sw-caster-consumer/pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ depends = ["swtest_base__module"]
2424

2525
[tool.semiwrap.extension_modules."sw_caster_consumer._module".headers]
2626
more = "cpp/more.h"
27+
28+
# checks that caster is included automatically when in a namespace
29+
ns_more = "cpp/ns_more.h"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <ns_inty.h>
4+
5+
namespace ns {
6+
7+
inline inty2 add_more_to_inty2(inty2 v, long value) {
8+
v.long_value += value;
9+
return v;
10+
}
11+
12+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
3+
functions:
4+
add_more_to_inty2:

tests/cpp/sw-test-base/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,7 @@ includedir = ["src/swtest_base/cpp/type_casters"]
4141
[[tool.semiwrap.export_type_casters.sw-test-base-casters.headers]]
4242
header = "inty_cast.h"
4343
types = ["inty"]
44+
45+
[[tool.semiwrap.export_type_casters.sw-test-base-casters.headers]]
46+
header = "ns_inty_cast.h"
47+
types = ["ns::inty2"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
namespace ns {
4+
5+
struct inty2 { long long_value; };
6+
7+
}
8+
9+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#pragma once
2+
3+
//
4+
// From pybind11 documentation
5+
//
6+
7+
#include <pybind11/pybind11.h>
8+
9+
#include "../ns_inty.h"
10+
11+
namespace pybind11 { namespace detail {
12+
template <> struct type_caster<ns::inty2> {
13+
public:
14+
/**
15+
* This macro establishes the name 'inty' in
16+
* function signatures and declares a local variable
17+
* 'value' of type inty
18+
*/
19+
PYBIND11_TYPE_CASTER(ns::inty2, const_name("swtest_base.inty"));
20+
21+
/**
22+
* Conversion part 1 (Python->C++): convert a PyObject into a inty
23+
* instance or return false upon failure. The second argument
24+
* indicates whether implicit conversions should be applied.
25+
*/
26+
bool load(handle src, bool) {
27+
/* Extract PyObject from handle */
28+
PyObject *source = src.ptr();
29+
/* Try converting into a Python integer value */
30+
PyObject *tmp = PyNumber_Long(source);
31+
if (!tmp)
32+
return false;
33+
/* Now try to convert into a C++ int */
34+
value.long_value = PyLong_AsLong(tmp);
35+
Py_DECREF(tmp);
36+
/* Ensure return code was OK (to avoid out-of-range errors etc) */
37+
return !(value.long_value == -1 && !PyErr_Occurred());
38+
}
39+
40+
/**
41+
* Conversion part 2 (C++ -> Python): convert an inty instance into
42+
* a Python object. The second and third arguments are used to
43+
* indicate the return value policy and parent object (for
44+
* ``return_value_policy::reference_internal``) and are generally
45+
* ignored by implicit casters.
46+
*/
47+
static handle cast(ns::inty2 src, return_value_policy /* policy */, handle /* parent */) {
48+
return PyLong_FromLong(src.long_value);
49+
}
50+
};
51+
}} // namespace PYBIND11_NAMESPACE::detail

0 commit comments

Comments
 (0)