【问题标题】:d2: importing function from external library under different name it was originally exportedd2:以不同的名称从外部库导入函数,它最初是导出的
【发布时间】:2012-04-05 13:34:36
【问题描述】:

我正在将用 C 编写的第 3 方库 API 转换为 D。该库导出了许多名为 libname_foofunclibname_barfunc 等的函数,这对于 C 库来说是可以防止膨胀的全局命名空间的。由于 D 比 C 更模块化,我想提供更多的 D'ish 接口并去掉函数前缀,所以函数看起来像 libname.c.foofunclibname.c.barfunc

由于图书馆不知道我的“改进”,我必须以某种方式将 libname.c.foofunc 翻译成 libname_foofunc 并同时保留正确的外部链接、目标名称修改和调用约定。

假设有办法(我也不知道)告诉链接器外部未解析符号 __imp__D1c7foofuncFZi 对应于 _libname_foofunclibname_foofunc@0(尽管我必须手动进行名称修改),有告诉 D 调用约定是什么仍然是个问题。

如果我在libname/c.di 中明确指定extern(C) int foofunc(),则不再存在调用约定问题,但名称被转换为_foofunc,这也与预期不同。

那么,在 D 中是否有办法以不同于导出的名称导入外部函数?

我曾考虑过以原始名称“按原样”导入函数,然后将它们别名为无前缀的类似物,但这似乎很笨拙。

【问题讨论】:

    标签: linker static-linking d


    【解决方案1】:

    你可以使用

    alias libname_foofunc foofunc;
    

    这将保持libname_foofunc 可见,但允许您使用foofunc,编译器会将其转换为libname_foofunc

    【讨论】:

    • 我在问题的最后一段中提到了这种临时解决方法。
    【解决方案2】:

    就链接而言,符号实际上是 C 的东西,因为我们谈论的是 C 链接器。 D 在链接和导出符号方面的情况与在 C++ 中的情况基本相同,这就是为什么会出现名称错误之类的原因。您将不得不在 D 中使用它们的原始名称为它们创建声明,因为这是链接器所期望的。 D 没有做任何不同或神奇的事情来改变这一点。只有两种方法可以使用不同的名称。

    1. 为 D 代码中的函数起别名。您可以将别名放在列出符号的任何模块中(因为无论如何您都必须在 D 中声明它们)。然后您的代码可以使用原始名称或别名。我没有看到任何笨拙的地方。

    2. 创建包装函数 - 在 C 或 D 中 - 并让您的 D 代码使用它们。

    别名肯定会更好恕我直言。它们不会引入任何开销并且不太复杂。

    但无论如何,在 D 中使用 C 库时,正常的做法就是使用 C 函数名。你正在调用 C 函数,这个事实不应该被隐藏。它们不是 D 函数,并且行为不同(即使它们相似) - 特别是在涉及到谁拥有你传递给函数的内存之类的东西时。重命名它们的好处是有争议的。通常是在编写 D 包装器以使 API 更清晰、更像 D 的 API(而不仅仅是更改名称)时,不再直接使用 C 函数。在 Phobos 中一个很好的例子是 etc.c.curl 与 std.net.curl。 etc.c.curl 纯粹是 C API,不会尝试重命名任何内容。它不会创建任何别名来使符号匹配 Phobos 的命名约定或使它们更像 D。它本质上只是 curl 头文件的 D 版本。另一方面,std.net.curl 建立在它之上以提供更像 D 的 API 和抽象。它不仅仅是重命名 C 函数。

    【讨论】:

      【解决方案3】:

      考虑到旧约的最后一段,答案是否定的。没有其他语言可以做到这一点,你描述的方式,它不应该。如果 API 设计人员想要以您喜欢的方式命名函数,他们会以这种方式公开它们......

      现在假设 A 组的开发人员更喜欢 some_function(),然后 B 组更喜欢 someFunction(),C 组更喜欢 SomeFunction()...

      别名是必须的,无论你使用 D 还是其他东西。它应该是这样的。 API 应该简单、简洁、易于理解。

      【讨论】:

        【解决方案4】:

        如果您不想将函数放入模块中,您可以将它们保存在结构中并模拟某种命名空间。例如。你可以这样做:

        struct libname
        {
            struct C
            {
                static int libname_foofunc();
                alias libname_foofunc foofunc;
            }
        
            static C c;
        }
        
        void main()
        {
            libname.c.foofunc();
        }
        

        【讨论】:

        • 哦,这个技巧看起来很巧妙——我可以将它声明为静态结构,所以static C c 中不需要...非常好,谢谢!
        • 是的,我没想过将定义设为静态。我不知道什么时候开始工作。 __gshared 也应该是静态的,__gshared 不会对这样的函数声明做任何事情。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-19
        • 1970-01-01
        • 2012-08-23
        • 1970-01-01
        • 2020-07-25
        • 1970-01-01
        相关资源
        最近更新 更多