0

xcode4.6でシンボルを非表示にすることにわずかな問題または誤解があります。Webのいたるところを検索しましたが、同じ問題の投稿は見つかりませんでした。

現在、次のような単純なヘッダーファイルを使用してフレームワークプロジェクトを作成しました。

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に切り替えられていることを確認しました。したがって、関数intcとクラスzのみが他のプロジェクトにエクスポートまたは表示されます。

エラーや警告なしでフレームワークを構築し、それをコピーしてcocoaアプリケーションに追加してテストします。

ヘッダーファイルをインクルードすることはできますが、それでもすべてのクラスと関数にアクセスできます。

誰かが私が間違っている理由や場所を説明できるか、以前にこの問題に遭遇したことがあるといいのですが?

よろしく

4

1 に答える 1

1

問題は、ヘッダーファイルですべてを宣言していることです。つまり、シンボルがエクスポートされていない場合でも、ヘッダーファイルを別のファイルにインポートすると、これらのシンボルはヘッダーをインポートしたプロジェクトで再作成されるため、もちろんこのプロジェクト内で使用できます。

簡単なサンプルでこれを説明しようとしています。MyLib.hとMyLib.cの2つのファイルがあるとします。

MyLib.h:

int add(int a, int b);

MyLib.c:

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

ここで可視性を与えaddhiddenすべてをライブラリ(MyLib)にコンパイルすると、ライブラリには(非表示になっているため)のシンボルがなくなりますadd。その結果、MyLib.h別のファイルにインクルードし、そこで関数を呼び出しadd、最後にこのファイルをに対してリンクするMyLibと、リンカーは実装が見つからないと文句を言うため、リンカーエラーが発生しますadd(宣言のみがあります)。 Hファイルから)。

ただし、関数をヘッダー自体にパックすると、MyLib.hは次のようになります。

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

可視性を与えるとaddhiddenライブラリにものシンボルはありませんaddが、ヘッダーを別のファイルに含めると、このヘッダーはaddそれをインポートしたファイルに正確にのシンボルを作成するため、もちろんリンカーエラーは発生しません。と呼び出すことができますadd

Hファイルをインポートするということは、Hファイルの内容全体をインポート命令が見つかった場所にコピーすることを意味します。考えてみてください。質問のHファイルのコンテンツ全体を、インクルードしているファイルの先頭にコピーすると、もちろん、そこで宣言されているすべてのシンボルが表示され、現在のプロジェクトで使用できます。なぜそれらは表示されないか、使用できないのですか?それらはライブラリにはありませんが、ヘッダーにあるため、他のプロジェクトがコンパイルされるときにコンパイルされます。

現在のプロジェクトの外部に表示されないはずのシンボル(「非表示」シンボル)は、フレームワークのパブリックヘッダーファイルに表示されないようにする必要があります。とにかく使用できないヘッダーファイルにシンボルが存在することを発表するのはなぜですか?実際、ほとんどの場合、ヘッダーファイル内のシンボルを公開しないことで、人々がそれらを使用できないようにするのに十分です。それらをエクスポートしない理由は、シンボルが存在する場合、ヘッダーファイルによって公開されていなくても使用できるためです(したがって、独自のヘッダーファイルを作成するかexternal、コードで直接シンボルとして宣言する必要があります) )。したがって、シンボルを非表示にすることは、どのような状況でも使用できないようにするための単なる保護手段です。

于 2013-02-19T13:16:03.547 に答える