【问题标题】:Why can't I create a MacOS framework with unresolved symbols?为什么我不能创建带有未解析符号的 MacOS 框架?
【发布时间】:2012-05-19 00:10:45
【问题描述】:

我认为动态库(以及 Apple 的 Mach-O 框架的扩展)的一个特性是在链接使用的应用程序之前保留一些符号(方法)未定义,但似乎所有符号都必须为 clang++ 解析为成功构建框架。

例如,在构建飞行模拟框架时,可能会留下一个名为 aero 的 C 例程未定义(但具有“extern aero()”规范。)但 XCode 4.2 拒绝构建框架,调用 @987654323 @ 一个“未定义的符号”。

这是 Objective-C 和 ANSI-C 例程包含的头文件:

// FlightVehicleCAdapter_data.h

#ifndef FlightVehicleCAdapter_data_h
#define FlightVehicleCAdapter_data_h

#ifdef __cplusplus
external "C" {
#endif

extern void aero( void );

#ifdef __cplusplus
}
#endif

这里是它被调用的地方:

// FlightVehicleCAdapter.m

-(void) calcAero {
    aero();
    [self setBodyAeroForce_lb:   [lsVector3 vectorFromScalarX:fv_data->f_aero_v.x
                                                            Y:fv_data->f_aero_v.y
                                                            Z:fv_data->f_aero_v.z]];
    [self setBodyAeroMoment_ftlb:[lsVector3 vectorFromScalarX:fv_data->m_aero_v.x
                                                            Y:fv_data->m_aero_v.y
                                                            Z:fv_data->m_aero_v.z]];

}

我曾希望能够在链接该框架的应用程序中定义真正的aero() 例程,但是当尝试构建框架 本身时,链接器拒绝在没有具体的情况下构建它aero() 实现:

Undefined symbols for architecture [i386|x86_64]:
  "_aero", referenced from:
    -[FlightVehicleCAdapter calcAero] in FlightVehicleCAdapter.o

然后我定义了一个虚拟的aero() 例程:

// dummy_aero.c
// not showing fv_data structure definition for clarity

void aero(void){
    fv_data->f_aero_v.x = 0.0; 
    fv_data->f_aero_v.y = 0.0;
    fv_data->f_aero_v.z = 0.0;

    fv_data->m_aero_v.x = 0.0;
    fv_data->m_aero_v.y = 0.0;
    fv_data->m_aero_v.z = 0.0;
}

aero()的这个定义满足clang++,这样Mach-O框架(动态库)就构建成功了。但是,当我将生成的框架与包含重要aero() 例程的应用程序目标链接时,将调用框架的虚拟aero() 而不是应用程序的aero()

【问题讨论】:

  • 如果您至少提供一些有关您正在做什么以及如何做的详细信息会有所帮助。
  • aero() 将在哪里定义?最终,它必须在某个地方定义。
  • 我编辑了问题以添加代码,感谢您的建议。希望它在某种程度上澄清了这个问题。我想在一个单独的应用程序中定义 aero() 将链接到这个框架,从而提供具体的 aero() 例程,但是如果没有具体的实现,框架就不会构建(这让我感到惊讶)。

标签: xcode macos frameworks


【解决方案1】:

您需要将-bundle_loader <executable> 选项传递给链接器,尽管我不确定它是否适用于框架。或者,您可以使用-undefined dynamic_lookup

【讨论】:

  • 是的!谢谢,肯,-undefined dynamic_lookup 修复了它。多么晦涩难懂!很高兴你知道,看到我的问题并花时间回答它!
【解决方案2】:

您需要为 aero() 执行此操作:

#ifdef __cplusplus
extern "C" {
#endif

extern void aero( void );

#ifdef  __cplusplus
}
#endif

这确保函数在 C++ 中声明为具有 C 可解析的名称。 C++ 构建名称的方式与 C 不同。

请注意,aero() 可以在运行时链接。

【讨论】:

  • “构建名称”被称为名称修改 :) en.wikipedia.org/wiki/Name_mangling
  • @Vlad - 是的,从那里我们可以谈论 ABI 等等,但 OP 显然是全新的,所以我有点想“先走后跑”。无论如何都要为您的评论 +1 :)
  • 这似乎没有必要,因为我在项目的这一部分中没有使用 C++,但我还是尝试了你的建议(并将其包含在修改后的问题中显示的示例中)无济于事;链接器在构建框架/动态库之前仍然需要 aero() 的具体定义。
猜你喜欢
  • 2012-02-03
  • 1970-01-01
  • 2021-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
相关资源
最近更新 更多