Browse Source

Add support for struct containing arrays

master
heck 4 years ago
parent
commit
e459df5781
  1. 16
      examples/ext/lib_test/lib_test/gen/config.json
  2. 2
      examples/ext/lib_test/lib_test/lib_test.cc
  3. 28
      examples/ext/lib_test/tests/test_lib_test.py
  4. 106
      pEpACIDgen/gen_backend/gen_pybind11.ysl2

16
examples/ext/lib_test/lib_test/gen/config.json

@ -5,6 +5,10 @@
"variables": [ "variables": [
], ],
"functions": [ "functions": [
"// func_TTAPSa_args_V",
"func_TACS_args_V"
],
"//functions": [
"func_V_args_V", "func_V_args_V",
"func_Pi_args_V", "func_Pi_args_V",
"func_V_args_Pi", "func_V_args_Pi",
@ -36,7 +40,17 @@
"func_pppTAPS_args_V", "func_pppTAPS_args_V",
"func_V_args_pTAPS", "func_V_args_pTAPS",
"func_ppTAPS_args_ppTAPS", "func_ppTAPS_args_ppTAPS",
"func_pppTAPS_args_pppTAPS" "func_pppTAPS_args_pppTAPS",
"func_TTAPSa_args_V",
"//func_TTAPSa_args_TTAPSa",
"//func_V_args_pTTAPSa",
"//func_ppTTAPSa_args_ppTTAPSa",
"//func_pppTTAPSa_args_pppTTAPSa",
"func_TACS_args_V",
"//func_TACS_args_TACS",
"//func_V_args_pTACS",
"//func_ppTACS_args_ppTACS",
"//func_pppTACS_args_pppTACS"
], ],
"debug_ast" : "True", "debug_ast" : "True",
"debug_acid" : "True", "debug_acid" : "True",

2
examples/ext/lib_test/lib_test/lib_test.cc

@ -1,10 +1,12 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <algorithm>
#include <pybind11/pybind11.h> #include <pybind11/pybind11.h>
#include <pybind11/detail/common.h> #include <pybind11/detail/common.h>
#include "lib_test.h" #include "lib_test.h"
using namespace std; using namespace std;
namespace py = pybind11;
PYBIND11_MODULE(lib_test, m) { PYBIND11_MODULE(lib_test, m) {
#include "gen/py_module.pybind11" #include "gen/py_module.pybind11"

28
examples/ext/lib_test/tests/test_lib_test.py

@ -251,6 +251,34 @@ def test_func_pppTAPS_args_pppTAPS():
assert(inout.field__P_1 == 23); assert(inout.field__P_1 == 23);
assert(inout.field__P_2 == 23); assert(inout.field__P_2 == 23);
def test_struct_field_array_of_structs_immutable_len():
a = CS()
b = PS()
assert(len(a.field_APS_1) == 3)
a.field_APS_1 = [b]
assert(len(a.field_APS_1) == 3)
a.field_APS_1 = [b,b]
assert(len(a.field_APS_1) == 3)
a.field_APS_1 = [b,b,b]
assert(len(a.field_APS_1) == 3)
a.field_APS_1 = []
assert(len(a.field_APS_1) == 3)
@pytest.mark.skip("throw exception instead of warnning")
def test_struct_field_array_of_structs_accept_unityped_arr_only():
a = CS()
b = PS()
with pytest.raises(Exception):
a.field_APS_1 = [b,"invalid_type"]
def test_struct_field_array_of_structs_of_structs_set_get():
a = CS()
b = PS()
b.field__P_1 = 23
b.field__P_2 = 23
a.field_APS_1 = [b]
assert(a.field_APS_1[0].field__P_1 == 23)
assert(a.field_APS_1[0].field__P_2 == 23)
def PS_to_string(ps): def PS_to_string(ps):

106
pEpACIDgen/gen_backend/gen_pybind11.ysl2

@ -4,6 +4,8 @@ tstylesheet {
template "module" { template "module" {
document("py_module.pybind11", "text") { document("py_module.pybind11", "text") {
|| ||
namespace py = pybind11;
// INSERT COOL ASCII ART HERE // INSERT COOL ASCII ART HERE
// METHOD // METHOD
`` apply "method" `` apply "method"
@ -37,19 +39,19 @@ tstylesheet {
[] []
( (
``apply "use", mode="arg_list_from_py" ``apply "use", mode="arg_list_from_py"
) -> pybind11::tuple ) -> py::tuple
{ {
``apply "return", mode="create" ``apply "return", mode="create"
``apply "use", mode="create_args_c" ``apply "use", mode="create_args_c"
`apply "return", mode="assign"`::«@name»( `apply "return", mode="assign"`::«@name»(
``apply "use", mode="arg_list_c" ``apply "use", mode="arg_list_c"
); );
return pybind11::make_tuple( return py::make_tuple(
`apply "return", mode="return"``if "count(use)>0" > ,` `apply "return", mode="return"``if "count(use)>0" > ,`
``apply "use", mode="return_args_as_tuple" ``apply "use", mode="return_args_as_tuple"
); );
}, },
pybind11::return_value_policy::copy); py::return_value_policy::copy);
|| ||
} }
@ -67,7 +69,7 @@ tstylesheet {
const "type", "@type"; const "type", "@type";
choose { choose {
when "contains($type,'void')" { when "contains($type,'void')" {
> pybind11::none() > py::none()
} otherwise { } otherwise {
choose { choose {
when "contains($type,'*')" { when "contains($type,'*')" {
@ -174,8 +176,8 @@ tstylesheet {
template "struct" { template "struct" {
|| ||
pybind11::class_<«@name»>(m, "«@name»") py::class_<«@name»>(m, "«@name»")
.def(pybind11::init([]() { return «@name»(); })) .def(py::init([]() { return «@name»(); }))
|| ||
apply "field" { apply "field" {
with "structname", "@name" with "structname", "@name"
@ -185,40 +187,86 @@ tstylesheet {
| |
} }
template "field" { template "field" {
param "structname"; param "structname";
|| param "name", "@name";
.def_property("«@name»", param "type", "@type";
[](::«$structname» &obj) -> «@type» { const "array_type", "substring-before($type, '[')";
//cout << "«$structname» ::«@name»: getter called" << endl; const "array_len", "substring-before(substring-after($type, '['),']')";
return obj.«@name»;
},
||
choose { choose {
when "@type = 'const char *'" { when "string-length($array_len) > 0" {
|| ||
[](::«$structname» &obj, «@type» cstr) -> void { .def_property("«$name»",
//cout << "«$structname»::«@name»: setter called" << cstr << endl; [](::«$structname» &obj) -> py::list {
obj.«@name» = strdup(cstr); //cout << "«$structname»::«$name»: getter called" << endl;
}, py::list l;
pybind11::return_value_policy::copy) for(int i=0; i < «$array_len»; ++i) {
|| l.append(obj.«$name»[i]);
}
return l;
},
[](::«$structname» &obj, py::list val) -> void {
// cout << "«$structname»::«$name»: getter called" << endl;
if(val.size() <= 0) {
// empty array given, doing nothing (static c array cant be cleared)
} else {
int cpy_amt = std::min(static_cast<int>(val.size()), «$array_len»);
bool isUnitypedArrayOf = true;
for(int i=0; i < cpy_amt; ++i) {
if (!py::isinstance<«$array_type»>(val[i])) {
isUnitypedArrayOf = false;
break;
}
}
if(!isUnitypedArrayOf) {
cout << "«$structname»::«$name» - setter error: is not a unityped array of type «$array_type»" << std::endl;
} else {
for(int i=0; i < cpy_amt; ++i) {
obj.«$name»[i] = val[i].cast<«$array_type»>();
}
}
}
},
py::return_value_policy::copy)
||
} otherwise { } otherwise {
|| ||
[](::«$structname» &obj, «@type» val) -> void { .def_property("«@name»",
//cout << "«$structname»::«@name»: setter called" << endl; [](::«$structname» &obj) -> «$type» {
obj.«@name» = val; //cout << "«$structname» ::«@name»: getter called" << endl;
}, return obj.«@name»;
pybind11::return_value_policy::copy) },
||
choose {
when "$type = 'const char *'" {
||
[](::«$structname» &obj, «$type» cstr) -> void {
//cout << "«$structname»::«@name»: setter called" << cstr << endl;
obj.«@name» = strdup(cstr);
},
py::return_value_policy::copy)
||
} otherwise {
||
[](::«$structname» &obj, «$type» val) -> void {
//cout << "«$structname»::«@name»: setter called" << endl;
obj.«@name» = val;
},
py::return_value_policy::copy)
|| ||
}
}
} }
} }
} }
template "enum" { template "enum" {
|| ||
pybind11::enum_<::«@name»>(m, "«@name»") py::enum_<::«@name»>(m, "«@name»")
``apply item ``apply item
; ;

Loading…
Cancel
Save