首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >共享库和c++20模块

共享库和c++20模块
EN

Stack Overflow用户
提问于 2021-10-05 14:54:56
回答 2查看 570关注 0票数 1

关于如何在共享库中正确使用C++20模块的在线文档很少。很多人are clearly interested,但我还没能找到一个明确的解决方案。

在MSVC中,在编译库时需要使用dllexport,在使用符号时需要使用dllimport。这可以使用“遗留C++”中的宏来完成,但这不适用于C++20模块,因为无论预处理器指令如何,代码只编译一次。

This post建议您现在只需要使用dllexportdllimport将由编译器自动处理。然而,这来自一条评论,现在已经被删除,我找不到任何关于这个话题的可靠来源。

如何使用C++20模块创建共享库?

EN

回答 2

Stack Overflow用户

发布于 2021-10-05 15:21:35

C++20模块与共享库没有特殊关系。它们主要是头文件的替换。

这意味着您将以类似于在C++20之前使用头文件的方式开发一个带有C++20模块的共享库,至少以我目前的理解是这样。您设计了一些导出的应用程序接口(遗憾的是,仍然使用特定于供应商的属性,如__declspec(dllexport)__attribute__((visibility("default"))))并实现它。您可以构建您的共享库文件(.dll/.so)和一个用于分发的导入库,方法与前面相同。但是,您应该分发模块接口单元,而不是分发头文件。模块接口单元是顶部包含export module ABC;声明的文件。

然后,使用该共享库的可执行文件将使用import ABC;导入该模块,而不是使用#include-ing头文件。

票数 0
EN

Stack Overflow用户

发布于 2021-10-11 01:31:58

背景

声明模块接口或模块分区的转换单元将被视为模块单元,并且在编译时将生成目标文件和二进制模块接口(BMI)。BMI是抽象语法树的二进制表示,抽象语法树是表示程序的语法和数据类型的数据结构。我们有传统的C++编译管道:

program ->预编译器->词法分析器->解析器->汇编器->链接器

对于GCC,我们应该添加编译器标志-c,它告诉编译器编译和汇编,而不是链接。

但是共享库是由链接器通过将几个编译的目标文件一起读取并创建一个共享对象来构建的。因此,这发生在BMI构建完成之后。BMI可以在不将它们连接在一起的情况下构建,因为这是两个不同的阶段。

模块可见性

在C#中,当构建动态链接库时,我们在类级别上有可见性属性,即。publicprivateinternal。在C++中,我们可以通过模块分区获得相同的功能。

使用module <module> : <partition>;声明的模块分区将在声明export module <module>;的编译单元内完全可见,但在该模块之外不可见。这让我想起了C#的internal模式。但是,如果我们使用export module <module> : <partition>;导出分区,那么它的声明将公开可见。有关cppreference的更多信息,请阅读。

示例

我已经用GCC (g++-11)解决了这个问题,参见here

本质上,您不需要DLL导入/导出,因为(很可能)不涉及任何头文件。我试过插入这些可见性属性,但我的编译器抱怨说,所以我猜我们可能根本不需要它们。除此之外,这是标准程序。我也在这里复制/粘贴我的示例:

Main

代码语言:javascript
复制
import <iostream>;
import mathlib;


int main()
{
    int a = 5;
    int b = 6;
    std::cout << "a = " << a << ", b = " << b << '\n';

    std::cout << "a+b = " << mathlib::add(a, b) << '\n';
    std::cout << "a-b = " << mathlib::sub(a, b) << '\n';
    std::cout << "a*b = " << mathlib::mul(a, b) << '\n';
    std::cout << "a/b = " << mathlib::div(a, b) << '\n';

    return 0;
}

图书馆

代码语言:javascript
复制
export module mathlib;

export namespace mathlib
{
    int add(int a, int b)
    {
        return a + b;
    }

    int sub(int a, int b)
    {
        return a - b;
    }

    int mul(int a, int b)
    {
        return a * b;
    }

    int div(int a, int b)
    {
        return a / b;
    }
}

Makefile

代码语言:javascript
复制
GCC=g++-11 -std=c++20 -fmodules-ts
APP=app

build: std_headers mathlib main

std_headers:
    $(GCC) -xc++-system-header iostream

mathlib: mathlib.cpp
    $(GCC) -c $< -o $@.o
    $(GCC) -shared $@.o -o libmathlib.so

main: main.cpp
    $(GCC) $< -o $(APP) -Xlinker ./libmathlib.so

clean:
    @rm -rf gcm.cache/
    @rm -f *.o
    @rm -f $(APP)
    @rm -f *.so

正在运行

代码语言:javascript
复制
g++-11 -std=c++20 -fmodules-ts -xc++-system-header iostream
g++-11 -std=c++20 -fmodules-ts -c mathlib.cpp -o mathlib.o
g++-11 -std=c++20 -fmodules-ts -shared mathlib.o -o libmathlib.so
g++-11 -std=c++20 -fmodules-ts main.cpp -o app -Xlinker ./libmathlib.so
./app
a = 5, b = 6
a+b = 11
a-b = -1
a*b = 30
a/b = 0

现在,这显然是特定于平台的,但该方法应该适用于其他平台。我也用Clang测试过类似的东西(与链接的repo相同)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69452740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档