Boost.Extension - simple inheritance sample - why we see no animals on linux?

核能气质少年 提交于 2019-12-18 09:05:38

问题


So I try to port some Boost.Extension samples for linux.

The sample is described here. Here is my code port (classes with animals, animal prototype, main app, general all port idea is described here, and some current linux progress here (some samples really work as needed!)). When I compile this sample under linux it compiles, it finds library with animals but outputs:

Animals not found!

Which shall happen only if(factories.empty()).

I try to port Extension samples onto crossplatform base - so I have tried same code under windows - works like a charm! finds all animals and outputs:

Creating an animal using factory:
Cougar factory Created an animal:
cougar Age: 2 Creating an animal using
factory: Leopard factory Created an
animal: leopard Age: 3 Creating an
animal using factory: Puma factory
Created an animal: puma Age: 4
Creating an animal using factory:
Wildcat factory Created an animal:
wildcat Age: 5

So... Why it behaves so on linux with same code? Why it works so well under Windows?

Update:

So how to build this stuff with premake:

  1. You get svn from here (only this folder is required)
  2. You get premake for your platform or build it from source and put it into folder you downloaded from svn
  3. You should have official Boost compiled and installed (please read ReadMe.txt file we provide in directory) so what is needed:
    • Boost C++ library's (we tested with version 1.4.16)
    • Boost-Extension ( we use latest revision , we adress it as part of boost 'boost/extension/**' We had to make some chandes (actually only one) to boost extension so we provide it inside Boost.Extension.Tutorial/libs/boost/extension/ folder so when you downloaded svn you got it, it is header only )
    • Boost-Reflection ( we use it because of this tutorial , we use latest revision , we adress it as part of boost 'boost/reflection/**' *and for simplness we recommend just to put it into Boost.Extension.Tutorial/libs/boost/reflection * )
  4. Now when official Boost is in your system, header only Boost-reflection and Boost-extension are in Boost.Extension.Tutorial/libs/boost folder, premake4 executable is inside Boost.Extension.Tutorial/ folder we can simply call Boost.Extension.Tutorial/ premake4-build-windows.bat on windows to get sln for Visual Studio or Boost.Extension.Tutorial/ premake-build.sh to get makefiles.
  5. You can find generated solution/makefiles inside generated projects folder.
  6. Have good luck!=)

Update 2:

Project files for Windows and Linux are now in svn so you can get aroung project creation with premake - just have Boost, our svn, and reflection headers only lib.


回答1:


I debugged things on linux, good news:

You are running into bullet no. 3 from Jeremy Pack's post:

RTTI does not always function as expected across DLL boundaries. Check out the type_info classes to see how I deal with that.

I have a tiny workaround patch (below) to boost/extension/impl/typeinfo.hpp (but you need to talk to the maintainer of Boost Extension, really). What this does is not rely on builtin comparison for RTTI typeinfo's.

Looking at typeinfo.hpp, it seems that Windows never actually uses the typeinfo comparison, so I decided to test with the 'strcmp' fallback method, and voila:

$ LD_LIBRARY_PATH=. ./Simple-Inheritance 
Creating an animal using factory: Cougar factory
Created an animal: cougar Age: 2
Creating an animal using factory: Leopard factory
Created an animal: leopard Age: 3
Creating an animal using factory: Puma factory
Created an animal: puma Age: 4
Creating an animal using factory: Wildcat factory
Created an animal: wildcat Age: 5

In particular, I can show that the type lookup from convertible_ fails at type_map.hpp, line 68;

  • When this conversion is called from the extension dll itself, the conversion happily finds the match using RTTI.
  • However, when the 'same' .get() is done from the test application (across DLL boundaries, i.e.) the RTTI is different and no such match is found, and line 74/75 are hit:

.

73        if (it == instances_.end()) {
74          holder = new type_holder<StoredType>;
75          it = instances_.insert(std::make_pair(t, holder)).first;
76        }

Patch

diff --git a/Boost.Extension.Tutorial/libs/boost/extension/impl/typeinfo.hpp b/Boost.Extension.Tutorial/libs/boost/extension/impl/typeinfo.hpp
index 843fed2..09fc353 100644
--- a/Boost.Extension.Tutorial/libs/boost/extension/impl/typeinfo.hpp
+++ b/Boost.Extension.Tutorial/libs/boost/extension/impl/typeinfo.hpp
@@ -50,7 +50,7 @@ struct type_info_handler<default_type_info, ClassType>

 // This list should be expanded to all platforms that successfully
 // compare type_info across shared library boundaries.
-#if defined(__APPLE__) || defined(__GNUC__) || \
+#if defined(__APPLE__) || \
     defined(BOOST_EXTENSION_FORCE_FAST_TYPEINFO)
 namespace boost {
 namespace extensions {
@@ -90,7 +90,7 @@ inline bool operator>(const default_type_info& first,
 }  // namespace extensions
 }  // namespace boost
 #else  // OTHER OS
-#include <string>
+#include <cstring>
 namespace boost { namespace extensions {
 inline bool operator<(const default_type_info& first,
                const default_type_info& second) {



回答2:


GCC on Linux by default has stricter linker optimization settings that MSVC on Windows. This leads to some factory patterns where classes register themselves as available appearing broken, simply because the linker optimizes away the classes. I didn't look at your code - but from the description it could be the problem.

A related question, with an answer on how to avoid the unreferenced classes being dropped: How to force gcc to link unreferenced, static C++ objects from a library



来源:https://stackoverflow.com/questions/5836948/boost-extension-simple-inheritance-sample-why-we-see-no-animals-on-linux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!