/* Copyright (C) 2010 The gtkmm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ // ugly code ahead. #include #include #include #include #include // utilities // Use this line if you want debug output: // std::ostream& ostr = std::cout; // This seems nicer and more useful than putting an ifdef around the use of std::cout: std::stringstream debug; std::ostream& ostr = debug; const unsigned int magic_limit(5); GList* create_list() { GList* head = nullptr; for (unsigned int iter(0); iter < magic_limit; ++iter) { head = g_list_prepend(head, g_credentials_new()); } return g_list_reverse(head); } void print_list(GList* list) { unsigned int counter(1); for (GList *node(list); node; node = node->next, ++counter) { ostr << counter << ": "; if (G_IS_CREDENTIALS(node->data)) { ostr << node->data << ", ref: " << G_OBJECT(node->data)->ref_count << "\n"; } else { ostr << "no C instance?\n"; } } } GSList* create_slist() { GSList* head = nullptr; for (unsigned int iter(0); iter < magic_limit; ++iter) { head = g_slist_prepend(head, g_credentials_new()); } return g_slist_reverse(head); } void print_slist(GSList* slist) { unsigned int counter(1); for (GSList *node(slist); node; node = node->next, ++counter) { ostr << counter << ": "; if (G_IS_CREDENTIALS(node->data)) { ostr << node->data << ", ref: " << G_OBJECT(node->data)->ref_count << "\n"; } else { ostr << "no C instance?\n"; } } } GCredentials** create_array() { GCredentials** array = g_new0(GCredentials*, magic_limit + 1); for (unsigned int iter(0); iter < magic_limit; ++iter) { array[iter] = g_credentials_new(); } return array; } void print_array(GCredentials** array) { for (unsigned int iter(0); iter < magic_limit; ++iter) { GCredentials* credentials(array[iter]); ostr << iter + 1 << ": "; if (G_IS_CREDENTIALS(credentials)) { ostr << reinterpret_cast(credentials) << ", ref: " << G_OBJECT(credentials)->ref_count << "\n"; } else { ostr << "no C instance?\n"; } } } // shallow copy GCredentials** copy_array(GCredentials** array) { GCredentials** dup = g_new0(GCredentials*, magic_limit + 1); for (unsigned int iter(0); iter < magic_limit; ++iter) { dup[iter] = array[iter]; } dup[magic_limit] = nullptr; return dup; } void free_array(GCredentials** array, bool container_too = true) { for (unsigned int iter(0); iter < magic_limit; ++iter) { g_object_unref(array[iter]); } if (container_too) { g_free(array); } } void print_vector(const std::vector>& v) { const unsigned int size(v.size()); for (unsigned int iter(0); iter < size; ++iter) { const Glib::RefPtr& obj_ptr(v[iter]); ostr << iter + 1 << ": "; if (obj_ptr) { GCredentials* gobj(obj_ptr->gobj()); if (G_IS_CREDENTIALS(gobj)) { ostr << static_cast(gobj) << ", ref: " << G_OBJECT(gobj)->ref_count << "\n"; } else { ostr << "No C instance?\n"; } } else { ostr << "No C++ instance?\n"; } } } struct Cache { public: Cache() : glist_(create_list()), gslist_(create_slist()), garray_(create_array()) {} ~Cache() { if (glist_) { g_list_foreach(glist_, reinterpret_cast(g_object_unref), nullptr); g_list_free(glist_); } if (gslist_) { g_slist_foreach(gslist_, reinterpret_cast(g_object_unref), nullptr); g_slist_free(gslist_); } if (garray_) { free_array(garray_); } } GList* get_list() const { return glist_; } GSList* get_slist() const { return gslist_; } GCredentials** get_array() const { return garray_; } private: // just in case Cache(const Cache&); Cache operator=(const Cache&); GList* glist_; GSList* gslist_; GCredentials** garray_; }; Cache& get_cache() { static Cache global_cache; return global_cache; } // C functions GList* c_get_deep_owned_list() { return get_cache().get_list(); } GList* c_get_shallow_owned_list() { return g_list_copy(c_get_deep_owned_list()); } GList* c_get_unowned_list() { return create_list(); } GSList* c_get_deep_owned_slist() { return get_cache().get_slist(); } GSList* c_get_shallow_owned_slist() { return g_slist_copy(c_get_deep_owned_slist()); } GSList* c_get_unowned_slist() { return create_slist(); } GCredentials** c_get_deep_owned_array() { return get_cache().get_array(); } GCredentials** c_get_shallow_owned_array() { return copy_array(c_get_deep_owned_array()); } GCredentials** c_get_unowned_array() { return create_array(); } /* these are probably buggy by design... void c_take_list_all(GList* list) { if(list) { print_list(list); g_list_foreach(list, reinterpret_cast(g_object_unref), 0); g_list_free(list); } } void c_take_list_members(GList* list) { if(list) { print_list(list); g_list_foreach(list, reinterpret_cast(g_object_unref), 0); } } */ void c_take_list_nothing(GList* list) { if (list) { print_list(list); } } /* they are probably buggy by design... void c_take_slist_all(GSList* slist) { if(slist) { print_slist(slist); g_slist_foreach(slist, reinterpret_cast(g_object_unref), 0); g_slist_free(slist); } } void c_take_list_members(GSList* slist) { if(slist) { print_slist(slist); g_slist_foreach(slist, reinterpret_cast(g_object_unref), 0); } } */ void c_take_slist_nothing(GSList* slist) { if (slist) { print_slist(slist); } } /* they are probably buggy by design... void c_take_array_all(GCredentials** array) { if(array) { print_array(array); free_array(array); } } void c_take_array_members(GCredentials** array) { if(array) { print_array(array); free_array(array, false); } } */ void c_take_array_nothing(GCredentials** array) { if (array) { print_array(array); } } // C++ wrappers. std::vector> cxx_get_deep_owned_list() { return Glib::ListHandler>::list_to_vector( c_get_deep_owned_list(), Glib::OWNERSHIP_NONE); } std::vector> cxx_get_shallow_owned_list() { return Glib::ListHandler>::list_to_vector( c_get_shallow_owned_list(), Glib::OWNERSHIP_SHALLOW); } std::vector> cxx_get_unowned_list() { return Glib::ListHandler>::list_to_vector( c_get_unowned_list(), Glib::OWNERSHIP_DEEP); } std::vector> cxx_get_deep_owned_slist() { return Glib::SListHandler>::slist_to_vector( c_get_deep_owned_slist(), Glib::OWNERSHIP_NONE); } std::vector> cxx_get_shallow_owned_slist() { return Glib::SListHandler>::slist_to_vector( c_get_shallow_owned_slist(), Glib::OWNERSHIP_SHALLOW); } std::vector> cxx_get_unowned_slist() { return Glib::SListHandler>::slist_to_vector( c_get_unowned_slist(), Glib::OWNERSHIP_DEEP); } std::vector> cxx_get_deep_owned_array() { return Glib::ArrayHandler>::array_to_vector( c_get_deep_owned_array(), Glib::OWNERSHIP_NONE); } std::vector> cxx_get_shallow_owned_array() { return Glib::ArrayHandler>::array_to_vector( c_get_shallow_owned_array(), Glib::OWNERSHIP_SHALLOW); } std::vector> cxx_get_unowned_array() { return Glib::ArrayHandler>::array_to_vector( c_get_unowned_array(), Glib::OWNERSHIP_DEEP); } /* they are probably buggy by design... void cxx_list_take_all(const std::vector >& v) { c_take_list_all(Glib::ListHandler >::vector_to_list(v).data()); } void cxx_list_take_members(const std::vector >& v) { c_take_list_members(Glib::ListHandler >::vector_to_list(v).data()); } */ void cxx_list_take_nothing(const std::vector>& v) { c_take_list_nothing(Glib::ListHandler>::vector_to_list(v).data()); } /* they are probably buggy by design... void cxx_slist_take_all(const std::vector >& v) { c_take_slist_all(Glib::SListHandler >::vector_to_slist(v).data()); } void cxx_slist_take_members(const std::vector >& v) { c_take_slist_members(Glib::SListHandler >::vector_to_slist(v).data()); } */ void cxx_slist_take_nothing(const std::vector>& v) { c_take_slist_nothing( Glib::SListHandler>::vector_to_slist(v).data()); } /* they are probably buggy by design... void cxx_array_take_all(const std::vector >& v) { c_take_array_all(Glib::ArrayHandler >::vector_to_array(v).data()); } void cxx_array_take_members(const std::vector >& v) { c_take_array_members(Glib::ArrayHandler >::vector_to_array(v).data()); } */ void cxx_array_take_nothing(const std::vector>& v) { c_take_array_nothing( Glib::ArrayHandler>::vector_to_array(v).data()); } int main() { Gio::init(); Cache& cache(get_cache()); ostr << "Cache list before:\n"; print_list(cache.get_list()); ostr << "Cache slist before:\n"; print_slist(cache.get_slist()); ostr << "Cache array before:\n"; print_array(cache.get_array()); ostr << "Deep owned list:\n"; print_vector(cxx_get_deep_owned_list()); ostr << "Shallow owned list:\n"; print_vector(cxx_get_shallow_owned_list()); ostr << "Unowned list:\n"; print_vector(cxx_get_unowned_list()); ostr << "Deep owned slist:\n"; print_vector(cxx_get_deep_owned_slist()); ostr << "Shallow owned slist:\n"; print_vector(cxx_get_shallow_owned_slist()); ostr << "Unowned slist:\n"; print_vector(cxx_get_unowned_slist()); ostr << "Deep owned array:\n"; print_vector(cxx_get_deep_owned_array()); ostr << "Shallow owned array:\n"; print_vector(cxx_get_shallow_owned_array()); ostr << "Unowned array:\n"; print_vector(cxx_get_unowned_array()); ostr << "Cache list after:\n"; print_list(cache.get_list()); ostr << "Cache slist after:\n"; print_slist(cache.get_slist()); ostr << "Cache array after:\n"; print_array(cache.get_array()); std::vector> v(cxx_get_unowned_list()); ostr << "Gotten vector before:\n"; print_vector(v); // I am wondering if C functions wrapped by the ones below are not buggy by // design. Anyway - it segfaults. Maybe the test case is just wrong. // ostr << "Take list all:\n"; // cxx_list_take_all(v); // ostr << "Take list members:\n"; // cxx_list_take_members(v); ostr << "Take list nothing:\n"; cxx_list_take_nothing(v); // Ditto. // ostr << "Take slist all:\n"; // cxx_slist_take_all(v); // ostr << "Take slist members:\n"; // cxx_slist_take_members(v); ostr << "Take slist nothing:\n"; cxx_slist_take_nothing(v); // Ditto. // ostr << "Take array all:\n"; // cxx_array_take_all(v); // ostr << "Take array members:\n"; // cxx_array_take_members(v); ostr << "Take array nothing:\n"; cxx_array_take_nothing(v); ostr << "Gotten vector after:\n"; print_vector(v); }