Boost.Extension - 简单继承示例 - 为什么我们在 Linux 上看不到动物?

发布于 2024-11-04 04:36:48 字数 3804 浏览 2 评论 0原文

所以我尝试为 Linux 移植一些 Boost.Extension 示例

此处描述了该示例。这是我的代码端口(动物类动物原型主应用,常规所有端口想法均在此处描述,以及 这里有一些当前的 Linux 进展(一些示例确实可以根据需要工作!))。当我在 Linux 下编译这个示例时,它会找到包含动物的库,但输出:

Animals not found!

这只会发生 if(factories.empty())

我尝试将扩展示例移植到跨平台基础上 - 所以我在 Windows 下尝试了相同的代码 - 就像魅力一样!找到所有动物并输出:

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

那么...为什么它在Linux上使用相同的代码表现如此?为什么它在Windows下运行得这么好?

更新:

那么如何使用 premake 构建这些东西:

  1. 你会得到 svn 来自此处(仅需要此文件夹)
  2. 为您的平台获取 premake 或从源代码构建它并将其放入您从 svn 下载的文件夹中
  3. 您应该编译并安装官方 Boost(请阅读我们在目录中提供的 ReadMe.txt 文件),所以需要什么:
    • Boost C++ 库(我们使用版本 1.4.16 进行测试)
    • Boost-Extension(我们使用最新版本,我们将其作为 boost 'boost/extension/的一部分**' 我们必须制作一些chandes(实际上只有一个)来增强扩展,因此我们将其提供在Boost.Extension.Tutorial/libs/boost/extension/文件夹中,以便当你下载 svn 时你就得到了它,它只是标题
    • Boost-Reflection(我们使用它因为本教程< /a> ,我们使用 最新版本 ,我们将其作为一部分boost 'boost/reflection/**' *为了简单起见,我们建议将其放入 Boost.Extension.Tutorial/libs/boost/reflection * )
  4. 现在,当您的系统中有官方 Boost 时,只有 Boost-reflection 和 Boost-extension 头文件位于 Boost.Extension.Tutorial/libs/boost 文件夹中,premake4 可执行文件位于 < code>Boost.Extension.Tutorial/ 文件夹中,我们可以简单地在 Windows 上调用 Boost.Extension.Tutorial/ premake4-build-windows.bat 来获取 Visual Studio 或 Boost 的 sln .Extension.Tutorial/ premake-build.sh 获取 makefile。
  5. 您可以在生成的项目文件夹中找到生成的解决方案/makefile。
  6. 祝你好运!=)

更新 2:

项目文件 适用于 Windows 和 Linux 的版本现在位于 svn 中,因此您可以使用 premake 来创建项目 - 只需拥有 Boost、我们的 svn 和反射标头专用库即可。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晌融 2024-11-11 04:36:48

我在 Linux 上调试了一些东西,好消息:

您遇到了 项目符号号。 3 来自 Jeremy Pack 的帖子

RTTI 并不总是按预期跨 DLL 边界运行。查看 type_info 类,看看我是如何处理这个问题的。

我有一个针对 boost/extension/impl/typeinfo.hpp 的小解决方法补丁(如下)(但您确实需要与 Boost Extension 的维护者交谈)。其作用依赖于 RTTI 类型信息的内置比较。

查看 typeinfo.hpp,似乎 Windows 从未真正使用过 typeinfo 比较,因此我决定使用“strcmp”后备方法进行测试,瞧:

$ 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

特别是,我可以显示从 convertible_convertible_ 进行的类型查找code> 在 type_map.hpp 第 68 行失败;

  • 当从扩展 dll 本身调用此转换时,转换会很高兴地使用 RTTI 找到匹配项。
  • 然而,当从测试应用程序执行“same”.get()时(跨DLL边界,即),RTTI不同并且没有找到这样的匹配,并且到达第74/75行:

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

修补

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) {

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) {
舟遥客 2024-11-11 04:36:48

默认情况下,Linux 上的 GCC 具有比 Windows 上的 MSVC 更严格的链接器优化设置。这会导致一些工厂模式,其中类将自身注册为可用,但看起来已损坏,这仅仅是因为链接器优化了类。我没有看你的代码 - 但从描述来看这可能是问题所在。

一个相关的问题,以及如何避免删除未引用的类的答案:如何强制 gcc 从库链接未引用的静态 C++ 对象

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文