Skip to content

Commit 1d799fb

Browse files
committed
Custom type wrapper
Add support of custem type wrappers : - add a hook function to allow declation of the custom wrappers - add a configuration parameter to provide a list of types whose wrappers should not be generated and assumed to be provided by code added to the generated one. Misc.: Graph.cpp code has been instrumented with extra debug messages than can be activated by changing in the code the value of a constant.
1 parent 63c300e commit 1d799fb

File tree

5 files changed

+132
-33
lines changed

5 files changed

+132
-33
lines changed

src/CodeTree.cpp

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,15 @@ std::ostream&
315315
CodeTree::generate_cxx_for_type(std::ostream& o,
316316
const TypeRcd& t){
317317

318+
//wrapper implemeted by the user
319+
if(is_custom_type_wrapper(t.type_name)){
320+
if(verbose > 1){
321+
std::cerr << "Info. Wrapper for type " << t.type_name
322+
<< " is configured as custom. Wrapper code generation skipped.\n";
323+
}
324+
return o;
325+
}
326+
318327
//if true, fake type used to hold global functions
319328
bool notype = t.type_name.size() == 0;
320329

@@ -595,6 +604,8 @@ CodeTree::generate_cxx(){
595604
o << "#include \"dbg_msg.h\"\n";
596605
o << "#include \"Wrapper.h\"\n";
597606

607+
o << "\nvoid end_hook(jlcxx::Module& jlModule) __attribute__((weak));\n";
608+
598609
std::vector<std::string> wrappers;
599610

600611
//File stream to write type wrapper,
@@ -700,6 +711,8 @@ CodeTree::generate_cxx(){
700711

701712
indent(o, 1) << "for(const auto& w: wrappers) w->add_methods();\n";
702713

714+
indent(o, 1) << "\nif(end_hook) end_hook(jlModule);\n";
715+
703716
o << "\n}\n";
704717
o.close();
705718
otimerstore.settimestamp();
@@ -2844,30 +2857,6 @@ void CodeTree::preprocess(){
28442857
}//next paramType
28452858
}//next iCombi
28462859

2847-
2848-
//Add user defined dependencies
2849-
for(const auto& dep: class_order_constraints_){
2850-
auto it1 = std::find_if(types_.begin(), types_.end(),
2851-
[dep](const auto& x){ return x.type_name == dep.first;});
2852-
auto it2 = std::find_if(types_.begin(), types_.end(),
2853-
[dep](const auto& x){ return x.type_name == dep.second;});
2854-
2855-
if(it1 != types_.end() && it2 != types_.end()){
2856-
type_dependencies_.preceeds(it1 - types_.begin(), it2 - types_.begin());
2857-
if(verbose > 1) std::cerr << "Dependency \"" << dep.second << " requires " << dep.first
2858-
<< "\" added.\n";
2859-
} else{
2860-
if(verbose>0){
2861-
std::cerr << "Warning: class dependency "
2862-
<< dep.first << " < " << dep.second
2863-
<< " not used.";
2864-
if(it1 == types_.end()) std::cerr << " No " << dep.first << " class.";
2865-
if(it2 == types_.end()) std::cerr << " No " << dep.second << " class.";
2866-
std::cerr << "\n";
2867-
}
2868-
}
2869-
}
2870-
28712860
#ifdef DEFINE_TEMPLATE_METHODS_IN_CTOR
28722861
//Add dependencies of templated classes to the type of their methods
28732862
//argument and return value.
@@ -2904,6 +2893,32 @@ void CodeTree::preprocess(){
29042893
} //next iChild
29052894
#endif
29062895

2896+
//Add user defined dependencies
2897+
for(const auto& dep: class_order_constraints_){
2898+
auto it1 = std::find_if(types_.begin(), types_.end(),
2899+
[dep](const auto& x){ return x.type_name == dep.first;});
2900+
auto it2 = std::find_if(types_.begin(), types_.end(),
2901+
[dep](const auto& x){ return x.type_name == dep.second;});
2902+
2903+
if(it1 != types_.end() && it2 != types_.end()){
2904+
type_dependencies_.preceeds(it1 - types_.begin(), it2 - types_.begin());
2905+
if(verbose > 1) std::cerr << "Dependency \"" << dep.second
2906+
<< "( node " << (it2 - types_.begin()) << ")"
2907+
<< " requires " << dep.first
2908+
<< "( node " << (it1 - types_.begin()) << ")"
2909+
<< "\" added.\n";
2910+
} else{
2911+
if(verbose>0){
2912+
std::cerr << "Warning: class dependency "
2913+
<< dep.first << " < " << dep.second
2914+
<< " not used.";
2915+
if(it1 == types_.end()) std::cerr << " No " << dep.first << " class.";
2916+
if(it2 == types_.end()) std::cerr << " No " << dep.second << " class.";
2917+
std::cerr << "\n";
2918+
}
2919+
}
2920+
}
2921+
29072922
if(verbose > 2){
29082923
std::cerr << "\nType list at end of preprocess:\n";
29092924
for(const auto& t: types_){
@@ -2918,8 +2933,10 @@ void CodeTree::preprocess(){
29182933

29192934
if(verbose > 2){
29202935
std::cerr << "\nType list at end of preprocess after reordering:\n";
2936+
size_t j = 0;
29212937
for(const auto i: types_sorted_indices_){
2922-
std::cerr << types_[i].type_name << "\n";
2938+
std::cerr << std::setw(4) << ++j << ". " << types_[i].type_name
2939+
<< " (" << i << ")\n";
29232940
}
29242941
std::cerr << "\n";
29252942
}
@@ -3160,21 +3177,61 @@ CodeTree::check_veto_list_for_var_or_field(const CXCursor& cursor, bool global_v
31603177
}
31613178
}
31623179

3180+
3181+
//FIXME: duplicate for template class
3182+
//strategy to adopt. add an extra_cursors vector to TypeRcd to keep tracks
3183+
//of duplicate and select the cursor with the largest number of visited elements.
3184+
//as main cursor.
31633185
int
31643186
CodeTree::add_type(const CXCursor& cursor, bool check){
31653187
const int not_found = -1;
31663188
int index = not_found;
3189+
bool spelling_duplicate = false;
3190+
CXCursor dup_cursor;
31673191
if(check){
31683192
int i = 0;
31693193
for(const auto& t: types_){
31703194
if(clang_equalCursors(t.cursor, cursor)){
31713195
index = i;
31723196
break;
31733197
}
3198+
if(str(clang_getCursorSpelling(t.cursor)) == str(clang_getCursorSpelling(cursor))){
3199+
spelling_duplicate = true;
3200+
dup_cursor = t.cursor;
3201+
}
31743202
++i;
31753203
}
31763204
}
31773205
if(index == not_found){
3206+
if(verbose > 0 && spelling_duplicate){
3207+
std::cerr << "Error. Duplicate definition of "
3208+
<< clang_getCursorSpelling(cursor)
3209+
<< " in the type list. This can lead to "
3210+
<< "improper wrapper definition order\n"
3211+
<< "first location: " << clang_getCursorLocation(dup_cursor)
3212+
<< "\n\tcursor kind: " << clang_getCursorKind(dup_cursor) << "\n"
3213+
<< "\n\tdeclaraion: " << (clang_isDeclaration(dup_cursor.kind) ? "yes" : "no") << "\n"
3214+
<< "\n\tFQN: " << fully_qualified_name(dup_cursor) << "\n"
3215+
<< "secon location: " << clang_getCursorLocation(cursor)
3216+
<< "\n\tcursor kind: " << clang_getCursorKind(cursor) << "\n"
3217+
<< "\n\tdeclaraion: " << (clang_isDeclaration(cursor.kind) ? "yes" : "no") << "\n"
3218+
<< "\n\tFQN: " << fully_qualified_name(cursor) << "\n"
3219+
<< "\n";
3220+
3221+
std::cerr << "First cursor contents:\n";
3222+
clang_visitChildren(dup_cursor, [](CXCursor cursor, CXCursor, CXClientData data){
3223+
std::cerr << cursor << "(" << clang_getCursorKind(cursor) << ")\n";
3224+
return CXChildVisit_Recurse;
3225+
}, nullptr);
3226+
3227+
std::cerr << "Second cursor contents:\n";
3228+
clang_visitChildren(cursor, [](CXCursor cursor, CXCursor, CXClientData data){
3229+
std::cerr << cursor << "(" << clang_getCursorKind(cursor) << ")\n";
3230+
return CXChildVisit_Recurse;
3231+
}, nullptr);
3232+
3233+
3234+
}
31783235
index = types_.size();
31793236
types_.emplace_back(cursor);
31803237
set_type_rcd_ctor_info(types_.back());
@@ -3715,7 +3772,7 @@ CodeTree::get_methods_to_wrap(const TypeRcd& type_rcd, bool quiet) const{
37153772
<< " not wrapped for type " << type_rcd.type_name
37163773
<< ", because of an overriding ambiguity in C++. Function "
37173774
"provided by the ancestor classes";
3718-
for(const auto& cl: m.second) std::cerr << ", " << cl.first.type_name << "\n";
3775+
for(const auto& cl: m.second) std::cerr << ", " << cl.first.type_name;
37193776
std::cerr << ".\n";
37203777
}
37213778
}

src/CodeTree.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,17 @@ namespace codetree{
301301
// Set map type for substitution in the C++ method prototypes declare to CxxWrap
302302
void set_cxx2cxx_typemap(const std::vector<std::string>& name_map);
303303

304+
void set_custom_wrapper_list(const std::vector<std::string>& l){
305+
custom_type_wrappers_ = l;
306+
}
307+
304308
protected:
305309

310+
bool is_custom_type_wrapper(const std::string type_name){
311+
return std::find(custom_type_wrappers_.begin(), custom_type_wrappers_.end(),
312+
type_name) != custom_type_wrappers_.end();
313+
}
314+
306315
enum class accessor_mode_t {none, getter, both };
307316

308317
// Adds a type to the list of types/classes to wrap.
@@ -634,6 +643,8 @@ namespace codetree{
634643
unsigned global_funcs = 0;
635644
} nwraps_;
636645

646+
647+
std::vector<std::string> custom_type_wrappers_;
637648
};
638649
}
639650

src/Graph.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
#include "Graph.h"
2+
3+
#include<iostream>
4+
5+
static constexpr const bool verbose_sorting = false;
6+
27
void Graph::extend(unsigned n){
38
if(n > edges_.size()){
49
edges_.resize(n);
@@ -38,6 +43,9 @@ void Graph::initScan(){
3843
cyclicmarks_.resize(edges_.size());
3944
fill(cyclicmarks_.begin(), cyclicmarks_.end(), false);
4045

46+
inserted_.resize(edges_.size());
47+
fill(inserted_.begin(), inserted_.end(), false);
48+
4149
cyclic_ = false;
4250
}
4351

@@ -53,25 +61,33 @@ void Graph::localSort(unsigned vertex){
5361

5462
/*check for all indices preceeding vertex*/
5563
for (const auto& node: edges_[vertex]){
56-
// std::cerr<< node << " (" << cyclicmarks_[node]
57-
// << ", " << cyclicmarks_[node] << ") "
58-
// << " ≺ "
59-
// << vertex << " (" << visited_[vertex]
60-
// << ", " << cyclicmarks_[vertex] << ") "
61-
// << "\n";
64+
if(verbose_sorting){
65+
std::cerr<< node << " (" << cyclicmarks_[node]
66+
<< ", " << cyclicmarks_[node]
67+
<< ", " << (inserted_[node] ? "in" : "")
68+
<< ") "
69+
<< ""
70+
<< vertex << " (" << visited_[vertex]
71+
<< ", " << cyclicmarks_[vertex]
72+
<< ", " << (inserted_[vertex] ? "in" : "")
73+
<< ") "
74+
<< "\n";
75+
}
6276
if (!visited_[node]){
6377
localSort(node);
6478
}
6579
cyclic_ |= cyclicmarks_[node];
66-
// std::cerr << "cyclic_: " << cyclic_ << "\n";
80+
//std::cerr << "cyclic_: " << cyclic_ << "\n";
6781
}
6882

6983
//remove the cycling detection mark:
7084
cyclicmarks_[vertex] = false;
7185

7286
//The node vertex has no not-yet-visited preceeding
7387
//node, add it to the sorted list:
88+
if(verbose_sorting) std::cerr << "add " << vertex << "\n";
7489
sortednodes_.push_back(vertex);
90+
inserted_[vertex] = true;
7591
}
7692

7793
void Graph::sort(){
@@ -82,6 +98,16 @@ void Graph::sort(){
8298
localSort(i);
8399
}
84100
}
101+
102+
if(verbose_sorting){
103+
std::cerr << "Sorted nodes: ";
104+
const char* sep = "";
105+
for(const auto & i: sortednodes_){
106+
std::cerr << sep << i;
107+
sep = "";
108+
}
109+
std::cerr << "\n";
110+
}
85111
sorted_ = true;
86112
}
87113

src/Graph.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class Graph {
4747
std::vector<std::list<unsigned>> edges_;
4848

4949
std::vector<bool> visited_;
50+
std::vector<bool> inserted_; //not need by algo, for debug
5051
std::vector<bool> cyclicmarks_;
5152
std::vector<unsigned> sortednodes_;
5253
bool cyclic_;

src/main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ int main(int argc, char* argv[]){
248248
out_cmake_fpath = resolve_out_dir("wrapit.cmake");
249249
}
250250

251+
auto custom_type_wrappers = read_vstring("custom_type_wrappers");
252+
251253
auto n_classes_per_file = toml_config["n_classes_per_file"].value_or(-1);
252254

253255
auto julia_names = read_vstring("julia_names");
@@ -383,6 +385,8 @@ int main(int argc, char* argv[]){
383385

384386
CodeTree tree;
385387

388+
tree.set_custom_wrapper_list(custom_type_wrappers);
389+
386390
tree.set_force_mode(options.count("force") > 0);
387391

388392
tree.set_ignore_parsing_errors(options.count("ignore-parsing-errors") > 0);

0 commit comments

Comments
 (0)