问题标签 [weak-linking]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
552 浏览

swift - 在运行时检查来自 Swift 第三方框架的弱链接符号

在 macOS 上,我使用必须由用户安装的外部框架(用 C 编写)。在 Swift 中,我需要在运行时检查它是否存在,并且我不能使用 #available() 因为它用于与操作系统相关的功能,并且我正在尝试追踪外部框架。此外, NSClassFromString() 没有用,因为它不是一个 Objective-C 框架。

我一直在尝试了解如何复制 Objective-C 等效项以检查弱链接符号,例如:

但在 Swift 中,这似乎不起作用:编译器指出,由于 anExternalFunction 不是可选的,我将始终得到 != nil,这使“Swift 有意义”,但对我没有一点帮助。

我找到了两种解决方案,但它们让我的代码变得很臭,就像你不会相信的那样:

选项 1,使用名为 isFrameworkAvailable() 的函数创建一个 Objective-C 文件,并从 Swift 调用

选项 2,实际使用以下 Swift 代码检查库:

我无法让选项 2 与 RTLD_DEFAULT 很好地配合使用,因为由于某种原因,它在 dlfcn.h (-2) 中定义,但似乎没有在 Swift 中导入(就像该标头中的所有负指针:RTLD_NEXT、RTLD_DEFAULT ,RTLD_SELF,RTLD_MAIN_ONLY)。我发现这个最丑陋的黑客使它起作用:

因此,对于选项 2,我需要路径或 hack,我发现它特别难看(但它有效),选项 1 不是很“Swifty”,对我来说没有什么意义:在 Swift 中这样做的正确方法是什么?

编辑:澄清问题,更好地解释选项 2。

0 投票
0 回答
62 浏览

c++ - 弱链接模板特化

是否可以定义弱链接模板特化?

在 math_functions.h 我有:

在 math_functions.cpp 中,我有模板专业化的默认实现,我希望这些实现可以被覆盖:

然后我有一个微控制器的目标特定文件,它应该提供更有效的 sqrt 功能,特定于硬件。我希望这个定义覆盖默认的 utils::sqrt<float> 专业化:

硬件.cpp:

我想做的甚至可能吗?

对于上面的代码,GCC 抱怨 utils::sqrt 的多个定义。

0 投票
2 回答
1564 浏览

c - 重定向断言失败消息

我们有一个具有实时约束的软件项目,主要用 C++ 编写,但使用了许多 C 库,在 POSIX 操作系统中运行。为了满足实时限制,我们已经将几乎所有的文本从stderr管道中注销并移到共享内存环形缓冲区中。

我们现在遇到的问题是,当旧代码或 C 库调用assert时,消息最终会stderr与其余日志一起出现在我们的环形缓冲区中,而不是在我们的环形缓冲区中。我们想找到一种方法来重定向assert.

这里我考虑了三种基本方法:

1.) 制作我们自己的断言宏——基本上,不要使用#include <cassert>,给我们自己的定义assert。这会起作用,但是要修补我们正在使用该调用的所有库assert以包含不同的标头会非常困难。

2.) 修补 libc - 修改 .libc 的实现__assert_fail。这会起作用,但在实践中会非常尴尬,因为这意味着我们无法在不构建日志基础设施的情况下构建 libc。我们可以这样做,以便在运行时,我们可以将函数指针传递给libc“断言处理程序”——这是我们可以考虑的。问题是是否有比这更简单/侵入性更小的解决方案。

3.) 修补 libc 标头,以便__assert_fail标有__attribute__((weak)). 这意味着我们可以在链接时使用自定义实现覆盖它,但是如果我们的自定义实现没有链接,那么我们将链接到常规的 libc 实现。实际上我希望这个功能已经被标记了__attribute__((weak)),我惊讶地发现它显然不是。

我的主要问题是:选项(3)的可能缺点是什么 - 修补 libc 以便这一行:https ://github.com/lattera/glibc/blob/master/assert/assert.h#L67

也标有__attribute__((weak))?

  1. 是否有充分的理由我没有想到维护人员还没有这样做?
  2. 在我以这种方式修补标头后,当前正在链接并成功针对 libc 运行的任何现有程序如何中断?这不可能发生,对吧?
  3. 出于某种原因在此处使用弱链接符号是否会产生显着的运行时成本?libc对我们来说已经是一个共享库,我认为动态链接的成本应该超过系统在加载时必须执行的任何关于弱分辨率与强分辨率的案例分析?
  4. 这里有我没有想到的更简单/更优雅的方法吗?

glibc 中的一些函数,特别是strtodmalloc,用特殊的 gcc 属性标记__attribute__((weak))。这是一个链接器指令——它告诉 gcc 这些符号应该被标记为“弱符号”,这意味着如果在链接时找到符号的两个版本,则选择“强”版本而不是弱版本。

维基百科上描述了这样做的动机:

用例

弱符号可以用作一种机制来提供函数的默认实现,这些函数可以在链接时被更专业的(例如优化的)函数替换。然后将默认实现声明为弱,并且在某些目标上,将具有强声明符号的目标文件添加到链接器命令行。

如果库将符号定义为弱符号,则链接该库的程序可以自由地提供强符号,例如用于定制目的。

弱符号的另一个用例是维护二进制向后兼容性。

但是,在 glibc 和 musl libc 中,在我看来,__assert_fail函数(assert.h宏转发到的)没有被标记为弱符号。

https://github.com/lattera/glibc/blob/master/assert/assert.h

https://github.com/lattera/glibc/blob/master/assert/assert.c

https://github.com/cloudius-systems/musl/blob/master/include/assert.h

0 投票
1 回答
257 浏览

ios - 静态库 iOS 中的弱链接

我们已经构建了一个静态框架,它依赖于我们用来访问 ID 的 SDK。该 SDK 推出了具有新界面的新版本。

目前,用户将添加我们的框架和依赖 SDK,一切都会正常工作。现在我们希望用户能够添加我们的框架以及旧的或新的 SDK,我不确定如何在不创建多个目标的情况下做到这一点,而我们不想这样做。通过我设置它的方式,用户必须添加我们的 SDK 以及新旧 SDK。

我有一个SDKProtocol由两个类NewSDKServicesOldSDKServices.

NewSDKServices除非存在新 SDK,OldSDKServices否则不会编译,除非存在旧 SDK,否则不会编译。我认为这没关系,因为它是一个预编译的框架,我们可以在运行时决定使用哪个。

然后我希望能够做这样的事情,也许ifdef可以导入和初始化正确的服务。

我考虑过弱链接这些库,但不确定它是如何工作的,因为你不能将框架静态链接到其他静态框架。我希望有一个方向。

两个 SDK 都有一些标头和一个.a.

0 投票
1 回答
210 浏览

c - 为什么 gcc 可以自动将符号标记为弱

我们使用 gcc4.1.2 构建了我们的代码,我们使用了在“sys/stat.h”系统头文件中定义的函数“lstat64”,并且也在我们使用的第三方库中定义。

当我们“nm”我们的可执行文件时,我们发现:

我的问题是:为什么 gcc 将其标记为弱功能?

另外,我们将代码移植到gcc4.4.4,我们发现新的gcc并没有将函数标记为“弱”,而是将其标记为未定义?

为什么会有这种行为变化?

0 投票
1 回答
544 浏览

c - __attribute__((weak) ) 函数导致未定义的引用

我目前正在尝试设置 CMock 以使用 MinGW 和 CMake 对 STM32 进行单元测试。在我的配置文件中,我设置了 :weak: 选项,这样生成的模拟就会给我弱功能。一个例子是:

但是,当我编译时,它给了我对 HAL_TIM_IC_Init 错误的未定义引用。

如果我删除weak属性,那么它不会给我未定义的引用错误。但是因为我需要重写HAL层提供的一些函数,所以需要将mocked库设为weak,否则会出现多个定义错误。

所以我的问题是为什么弱属性会导致未定义的引用错误,我该如何解决?

0 投票
1 回答
455 浏览

ios - 位码是否支持弱链接第三方框架?

问题在标题中简单说明。这是我的设置:

构建一个动态框架,可选择链接(弱链接)到 GoogleInteractiveMediaAds.framework。对于使用我的框架的应用程序,GoogleInteractiveMediaAds 是一个可选依赖项,没有它框架也能正常工作。这目前正在工作。

但是,当尝试从位码重建时会出现问题,这通常发生在选择“从位码重建”导出 Ad Hoc 构建时。位码编译过程失败:

并深入查看日志文件,我发现错误描述:

注意:GoogleInteractiveMediaAds.framework 确实包含位码。

显然,通过不选择“从位码重建”来避免此错误。如果我要回答我自己的问题,我会说,不,看起来从位码编译时,你不能使用弱链接框架。仅仅因为位码编译步骤试图链接到应用程序目标中未包含的框架。但是,我无法找到任何使用位码弱链接的官方文档,或任何相关的 StackOverflow 答案,所以我不确定我是否遗漏了什么或者是否有一些相关的编译器/链接器设置我错过了让它工作。

0 投票
1 回答
313 浏览

c++ - 在编译时检查静态函数是否存在

功能。c (我不能编辑这个文件)

cpp

我想做同样的事情,但不使用TESTmain.cpp 文件中的定义

我想做的事:

如果尚未声明CppFoo()静态函数,则不必声明该方法。Foo()

我怎样才能做到这一点?

0 投票
1 回答
318 浏览

c - 为所有函数设置 GCC 默认属性(让所有函数符号对猴子补丁来说都是弱的)

我目前正在编写一个包含单独测试构建的 C 项目。

测试是不同的 C 进程,它们使用源代码来测试我的代码 (TDD) 中定义的每个函数。

我想在这些测试中进行猴子修补。我花了一些时间看看它可以做什么,我认为最简单的选择是使用 gcc 属性功能:https ://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html

对于测试构建,我希望我的所有函数都是弱的(IE,我想要的效果就像我__attribute__ (( weak))在 C 文件的任何函数声明之前写的一样。)

我想知道是否有一种方法可以在默认情况下将这个弱属性作为编译选项传递,而不是在每次需要时手动进行。现在我正在使用一个宏来测试构建是否在测试中,如果是,则在我想要的每个函数之前添加这一行。我宁愿避免复杂化源代码只是为了允许一些测试功能。

google 上的这个主题被重复使用相同的琐碎属性所污染,但我找不到任何设置属性默认值的方法。

但是,我发现这本书https://link.springer.com/chapter/10.1007%2F978-1-4302-0704-7_4可能包含解决方案,但我不会为此支付 30 美元。所以我在这里问这个问题。

有些人可能认为这是一个坏主意,但在我的情况下,我认为这很好。请记住,我的测试套件由许多与我的代码链接的单声道 C 文件组成,并且请记住,正常的构建不会受到新的测试构建选项的影响。

0 投票
1 回答
312 浏览

c++ - 你能像 Objc 一样弱链接(可选链接)C++ 中的静态库吗?

我正在开发一个在 Xcode 中混合了 Objective C 和 C++ 的静态库A,我遇到了“弱链接”另一个静态库的需要,我们称之为BA调用B中定义的一些方法。这个想法是,如果B没有链接/提供,A将不会抛出任何未定义的符号错误。我知道在Objective C中你可以做到这一点,在代码中我可以依靠运行时方法,如NSClassFromString或[someObject Class]来检查某个函数是否存在/是否可从另一个静态库中获得,但我不知道是否我可以在我的一个 .cpp 源文件中实现这一点。请指教,谢谢!

为了说明目的,我创建了一个非常简单的示例项目:

图书馆A

Core_ObjC.h,这是要暴露的头文件

Core_ObjC.mm

Core_CPP.cpp

图书馆B

NonCore_CPP.cpp

如果我在示例应用程序中链接这两个库,则该应用程序将正常编译。但是,当我从示例应用程序中仅链接 A 时,我会遇到如下错误:

该错误对我来说确实有意义,因为B将缺少定义,但我只是在寻找一个解决方案,当只有A时编译不会抱怨。