我在xcode 4.6中隐藏符号时遇到了一些小问题或误解。我已经在网络上的任何地方搜索过,无法找到任何有相同问题的帖子。
目前我已经创建了一个框架项目,其中包含一个简单的头文件,其中包含:
class Test
{
public:
Test(){}
Test(){}
};
int a(int n) {return n;}
__attribute__((visibility("hidden"))) int b(int n) {return n;}
__attribute__((visibility("default"))) int c(int n) {return n;}
class X
{
public:
virtual ~X();
};
class __attribute__((visibility("hidden"))) Y
{
public:
virtual ~Y();
};
class __attribute__((visibility("default"))) Z
{
public:
virtual ~Z();
};
X::~X() { }
Y::~Y() { }
Z::~Z() { }
在项目设置中,我确保“默认隐藏的符号”切换为YES,因此只有int c和class z的函数将被导出或显示给其他项目。
我构建了没有错误或警告的框架,然后将其复制/添加到cocoa应用程序进行测试。
我能够包含头文件,但我仍然可以访问所有类和函数。
我希望有人可以解释为什么或哪里出错或者之前遇到过这个问题?
问候
答案 0 :(得分:1)
您的问题是,您正在声明标头文件中的所有内容。这意味着即使未导出符号,当您将头文件导入另一个文件时,这些符号也会在您导入标题的项目中重新创建,因此它们当然可以在此项目中使用。
我试图通过一个更简单的样本向您解释。假设您有两个文件,MyLib.h和MyLib.c。
MyLib.h:
int add(int a, int b);
MyLib.c:
int add(int a, int b) { return a + b };
如果您现在为add
提供hidden
可见性并将所有内容编译到库(MyLib
),则该库将没有add
的符号(因为它是隐藏的) )。因此,如果您将MyLib.h
包含到另一个文件中,请在那里调用add
函数并最终将此文件与MyLib
相关联,您将收到链接器错误,因为链接器会抱怨它无法找到add
的实现(它只有H文件中的声明)。
但是,如果将函数打包到标题本身,那么MyLib.h就是:
int add(int a, int b) { return a + b };
并且您add
hidden
可见,该库也没有add
的符号,但是当您将标题包含到另一个文件中时,此标题将为add
正好在导入它的文件中,因此您当然不会收到链接器错误并且能够调用add
。
导入H文件只是意味着将H文件的全部内容复制到找到导入指令的位置。现在考虑一下:如果你将问题中H文件的全部内容复制到包含它的文件的顶部,当然所有在那里声明的符号在当前项目中都是可见的和可用的。为什么它们不可见或不可用?它们不在库中,是的,但是它们位于标题中,因此在编译其他项目时会进行编译。
在当前项目之外看不到的符号(“隐藏”符号)不应出现在框架的任何公共头文件中。为什么要宣布无法使用的头文件中是否存在符号?实际上,在大多数情况下,不暴露头文件中的符号已足以阻止人们使用它们。不导出它们的原因只是如果符号存在,它可以被使用,即使它没有被任何头文件公开(因此你只需要编写自己的头文件或将其声明为external
直接在你的代码中的符号)。因此,隐藏符号只是一种保障,以确保它在任何情况下都不能使用。