Windows MinGW64 不导出类体内定义的成员(静态或非静态)函数

2023-12-12

我已经更新了代码示例并添加了更多详细信息,因为有些人在评论中说该代码不应生成任何导出的符号句点。


我还在这些方法中添加了一些实现,但在使用 MinGW 和 Clang 导出符号方面没有任何改变。 (没更新objdump虽然输出。本质上他们没有改变太多)。


从可执行文件导出符号时,我遇到了一个非常烦人的问题。

考虑以下代码:

# CMakeLists.txt

add_executable(app main.cpp)
set_target_properties(app PROPERTIES ENABLE_EXPORTS 1)

add_library(lib SHARED main.cpp)
// main.cpp
class __declspec(dllexport) foo
{
public:
    int bar()
    {
        static int val = 3;
        return ++val;
    }
    static int buz()
    {
        static int val = 814;
        return ++val;
    }
};

template <typename T>
class __declspec(dllexport) foo_t
{
public:
    int bar()
    {
        static int val = 3;
        return ++val;
    }
    static int buz()
    {
        static int val = 814;
        return ++val;
    }
};

template class foo_t<int>;

int main()
{
    return 0;
}

MSVC

编译时生成可执行文件和dllxxx.lib带有可用于链接的导出符号。

// DUMPBIN.exe /EXPORTS app.lib (exact same as for lib.lib)

Dump of file lib.lib

File Type: LIBRARY

     Exports

       ordinal    name

                  ??4?$foo_t@H@@QEAAAEAV0@$$QEAV0@@Z (public: class foo_t<int> & __cdecl foo_t<int>::operator=(class foo_t<int> &&))
                  ??4?$foo_t@H@@QEAAAEAV0@AEBV0@@Z (public: class foo_t<int> & __cdecl foo_t<int>::operator=(class foo_t<int> const &))
                  ??4foo@@QEAAAEAV0@$$QEAV0@@Z (public: class foo & __cdecl foo::operator=(class foo &&))
                  ??4foo@@QEAAAEAV0@AEBV0@@Z (public: class foo & __cdecl foo::operator=(class foo const &))
                  ?bar@?$foo_t@H@@QEAAXXZ (public: void __cdecl foo_t<int>::bar(void))
                  ?bar@foo@@QEAAXXZ (public: void __cdecl foo::bar(void))
                  ?buz@?$foo_t@H@@SAXXZ (public: static void __cdecl foo_t<int>::buz(void))
                  ?buz@foo@@SAXXZ (public: static void __cdecl foo::buz(void))

可以看出,两者foo和模板foo_t方法已导出。

Clang

Dump of file libapp.dll.a

File Type: LIBRARY

     Exports

       ordinal    name

                  _ZN5foo_tIiE3barEv
                  _ZN5foo_tIiE3buzEv
                  _ZN5foo_tIiEaSERKS0_

因为只能看到foo_t方法已导出并且仅由于显式模板实例化。如果删除显式模板实例化,则不会有libapp.dll.a。不过会有liblib.dll.a虽然有一个空EXPORTS部分。

MinGW64

Dump of file liblib.dll.a

File Type: LIBRARY

     Exports

       ordinal    name

                  main
                  _ZN5foo_tIiE3buzEv
                  _ZN5foo_tIiE3barEv

与 Clang 一样,它仅导出显式模板实例化方法。
但与 Clang 和 MSVC 不同没有libapp.dll.a生成可执行文件!

// objdump -t app.exe

File 
[116](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000000016c0 .text$_ZN5foo_tIiE3barEv
AUX scnlen 0xb nreloc 0 nlnno 0 checksum 0x0 assoc 0 comdat 2
[118](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 1) 0x00000000000016c0 _ZN5foo_tIiE3barEv
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[120](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x00000000000016d0 .text$_ZN5foo_tIiE3buzEv
AUX scnlen 0x7 nreloc 0 nlnno 0 checksum 0x0 assoc 0 comdat 2
[122](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000000016d0 _ZN5foo_tIiE3buzEv

可执行文件本身包含显式实例化模板的符号foo_t方法。为什么没有为可执行文件生成静态库?

结论

  1. 在动态库的所有情况下,静态库中都有导出的符号(libxxx.a or xxx.lib) 用于显式类模板实例化。但 MinGW64 不会为可执行文件生成静态库。为什么?
  2. 仅 MSVC 导出非模板类隐式内联方法的符号。为什么?这是跨平台应用程序可以依赖的预期行为吗?
  3. 为什么导出模板类和非模板类的隐式内联类内实现方法之间存在不一致(非模板不导出)?跨平台应用程序可以依赖导出的模板类方法作为保证吗?

要深入了解该问题,请参阅https://github.com/skypjack/entt/issues/719


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows MinGW64 不导出类体内定义的成员(静态或非静态)函数 的相关文章

  • C++:如何检测向量中的重复项并打印一份副本?

    我是 C 新手 我想知道如何在向量中找到重复的字符串并打印出该字符串的一个副本 例如 如果我有它会打印出cat dog bird 我已经对我的向量进行了排序 并使用adjacent find函数并迭代该向量 因为我必须查找是否有任何单词重复
  • 如何使用 VS2022 中的新控制台应用程序模板访问命令行参数

    我想知道如何访问命令行参数 因为这是在Program cs通过 Visual Studio 2022 中控制台应用程序的新模板创建文件 See https aka ms new console template for more infor
  • 在哪里使用 EF6 订阅 ObjectMaterialized?

    我正在尝试将我的上下文订阅到以下 OnjectMaterialized 事件this https stackoverflow com a 3756842 2835713 像这样 IObjectContextAdapter this Obje
  • 将列表数组中的值绑定到列表框

    任何机构都可以给出一个简短的示例 用于将列表数组中的值绑定到 c net 中的列表框 这取决于您的列表数组的情况 让我们从一个简单的示例开始 List
  • 在 C++ 中,std::string::push_back() 的摊余复杂度是 O(1) 吗?

    我知道标准指定它适用于向量 但是字符串呢 是的 它是摊销常数时间 请参见第 716 页的表 101本文件的 http www open std org jtc1 sc22 wg21 docs papers 2012 n3485 pdf 表
  • 如何自定义 ASP.Net Core 模型绑定错误?

    我只想从我的 Web API Asp net Core 2 1 返回标准化的错误响应 但我似乎不知道如何处理模型绑定错误 该项目刚刚从 ASP NET Core Web 应用程序 gt API 模板创建 我有一个简单的操作定义为 Route
  • 使用 Process.Start() 打开文件夹时访问被拒绝异常

    我有一个 C 中的 winforms 应用程序 我必须在其中打开某个文件夹 我用 System Diagnostics Process Start pathToFolder 这会导致以下异常 System ComponentModel Wi
  • C++ Linux GCC 应用程序中的 GUID

    我有很多服务器运行这个 Linux 应用程序 我希望他们能够生成一个碰撞概率较低的 GUID 我确信我可以从 dev urandom 中提取 128 个字节 这可能没问题 但是有没有一种简单易用的方法来生成与 Win32 更等效的 GUID
  • 是否可以获取指向装箱非托管值类型的指针?

    是否可以获取指向装箱非托管值类型的指针 而无需编写对每个支持的类型进行强制转换的大型 switch 语句 就像是 object val Contains a boxed unmanaged value such as int long by
  • 为什么 .Net 框架指南建议您不要使用 ref/out 参数?

    显然 他们很 混乱 这是认真的原因吗 你还能想到其他的吗 你见过有多少开发人员并不真正理解 ref out 吗 我在真正需要的地方使用它们 但在其他地方则不然 它们通常仅在您想有效返回两个或多个值时才有用 在这种情况下它至少值得thinki
  • memccpy 返回比 src 起始地址更低的内存地址

    我有一个学校项目 我必须重新编码memccpy 功能 我使用 2 个程序来检查我的代码是否正常工作 第一个是只有一个主程序的小程序 第二个程序是另一个学生开发的 可以找到here https github com yyang42 mouli
  • 如何实现可变虚拟成员函数

    所以我有这个功能 virtual void CallRemoteFunction const char pServerGameObjectId const char pFunctionName OVariant arg1 OVariant
  • 为什么我在这段代码中不断得到两个相同的随机值? [复制]

    这个问题在这里已经有答案了 可能的重复 为什么我的随机数生成器在 C 中不是随机的 https stackoverflow com questions 932520 why does it appear that my random num
  • 不可能的事情发生了!这是什么意思?

    我遇到了一个有趣的运行时错误 我认为这是某种内存泄漏 我写了以下程序 C Code include
  • 为什么我从 c# 到 js 得到不同的 MD5 哈希值?

    我有一个用于加密密码的 C 函数 System Security Cryptography MD5CryptoServiceProvider md5Provider new System Security Cryptography MD5C
  • 验证域用户凭据

    我需要一种方法来验证 Windows 上本机 C 的用户 密码对 输入的是用户名和密码 用户可以是 DOMAIN user 格式 基本上我需要编写一个函数 如果用户 密码是有效的本地帐户 则返回 true 第1部分 如果用户 密码在给定的域
  • 更改成员资格、角色等的默认连接字符串

    默认情况下 我的网络应用程序似乎正在使用LocalSqlServer作为用于任何应用程序服务 例如成员资格 角色 身份验证 等 的连接字符串 有什么方法可以更改默认连接字符串应该是什么 默认值是 LocalSqlServer 似乎很随意 我
  • 不兼容的指针到字符转换

    我正在编写一个程序 将卡片值写入 52 个点字符的多维数组中 该程序是一个测试数组 稍后我将其作为函数写入主程序中 在程序中 我通过以下方式初始化 for 循环计数0通过51 我用一个switch语句调制13将卡牌值分配给数组点 但是 我收
  • 在标准 C 中将 int 转换为 string

    我是 C 新手 我正在寻找一个可以调用函数进行转换的示例int串起来 我发现itoa但这不是标准 C 的一部分 我还发现sprintf str d aInt 但问题是我不知道所需的 str 的大小 因此 我如何传递输出字符串的正确大小 有多
  • C# 中的快速字符串解析

    在 C 中解析字符串最快的方法是什么 目前我只是使用字符串索引 string index 并且代码运行合理 但我忍不住认为索引访问器所做的连续范围检查必须添加一些东西 所以 我想知道我应该考虑哪些技术来增强它 这些是我最初的想法 问题 使用

随机推荐