昨日、Xcodeを(5.1 (5B130a))
と互換性のある最新バージョンiOS 7.1
に更新しました。その後、プロジェクトをビルドすると、64ビットシミュレーター(例:iPhone Retina 4-inch 64-bit)が選択されているときに、エラー"Cast from pointer to smaller type 'int' loses information"
in EAGLView.mm
ファイル(line 408
)が表示されます。
cocos2d-x-2.2.2
を使用しています。 Xcodeを更新する前に、私のプロジェクトはすべてのデバイスで正常にビルドおよび実行できます。
すべての推奨をありがとう。
更新:今日、最新バージョンのcocos2d-x(cocos2d-x 2.2.3)をダウンロードします。しかし、問題はまだ発生しています。
そのエラーが発生するコードの一部を次に示します。
/cocos2d-x-2.2.2/cocos2dx/platform/ios/EAGLView.mm:408:18: Cast from pointer to smaller type 'int' loses information
// Pass the touches to the superview
#pragma mark EAGLView - Touch Delegate
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (isKeyboardShown_)
{
[self handleTouchesAfterKeyboardShow];
return;
}
int ids[IOS_MAX_TOUCHES_COUNT] = {0};
float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};
int i = 0;
for (UITouch *touch in touches) {
ids[i] = (int)touch; // error occur here
xs[i] = [touch locationInView: [touch view]].x * view.contentScaleFactor;;
ys[i] = [touch locationInView: [touch view]].y * view.contentScaleFactor;;
++i;
}
cocos2d::CCEGLView::sharedOpenGLView()->handleTouchesBegin(i, ids, xs, ys);
}
明らかに、Xcode 5.1以降のclangバージョンは、以前のclangバージョンよりも、ソースコードの潜在的な32ビットと64ビットの非互換性についてより厳密です。正直なところ、clangはここでは制限が厳しすぎると思います。正常なコンパイラーは、このような行に警告をスローする場合がありますが、エラーをスローするべきではありません。
元のコードは
ids[i] = (int)touch;
idsはintの配列であり、touchはポインターです。
64ビットビルドでは、ポインターは64ビット(32ビットの場合は32ビットビルドとは反対)であり、intは32ビットであるため、この割り当ては32ビットストレージに64ビット値を格納し、情報の損失を招く可能性があります。
したがって、コンパイラが次のような行に対してエラーをスローすることは完全に有効です。
ids[i] = touch;
ただし、問題の実際のコードには、intへの明示的なcスタイルのキャストが含まれています。この明示的なキャストは、コンパイラに「黙って、このコードが正しく見えないことは知っているが、自分が何をしているのかは知っている」とはっきりと伝えています。
したがって、コンパイラはここで非常に選り好みし、コードを再度コンパイルし、Xcode 5.0とまったく同じ動作をさせる正しいソリューションは、最初にポインタのサイズと一致するサイズの整数型にキャストすることです次に、実際に必要なintへの2回目のキャストを行います。
ids[i] = (int)(size_t)touch;
プラットフォームに関係なく、常にポインタと同じサイズであるため、ここではsize_tを使用しています。 long longは32ビットシステムでは機能せず、longは64ビットWindowsで機能しません(64ビットUnixおよびOS XのようなUnixライクシステムはLP64データモデルを使用し、longは64ビット、64ビットWindowsはLLP64データを使用しますモデルでは、longのサイズは32ビットです( http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models ))。
このids[i] = (int)touch;
をids[i] = (uintptr_t)touch;
に置き換えます
わたしにはできる。
私もこの問題に直面しています。
ids[i] = (int)touch;
//ここでエラーが発生しました=>これを以下に変更します。
ids[i] = (uintptr_t)touch;
その後、コンパイルを続行できます。たぶん、あなたもこれを試すことができます。
XCode 5.1は、すべてのアーキテクチャを64ビットに変更します。
ビルド設定で以下のすべてによって32ビットコンパイルをサポートするようにアーキテクチャを変更することができます
それが役に立てば幸い。
intの代わりにuintptr_tを使用できます。その標準に続いてXcode。
このコード行を置き換えることにより、このエラーを修正できます。
ids [i] =(uint64_t)touch;
タイプ「int」は-32768〜32768のみをサポートするため、64ビットビルドシステムに基づいてタイプ変換を実行する必要があります。
解決策は、IDの型をintからポインターを保持するのに十分な大きさの型に変更することです。
私はXCodeに不慣れですが、解決策は次のようなものでなければなりません:
IDの宣言を次のように変更します。
intptr_t ids[IOS_MAX_TOUCHES_COUNT];
エラーを生成する行:
ids[i] = (intptr_t)touch;
上記の「解決策」のほとんどは、小さな型にキャストするときにポインターアドレスの一部を失う可能性があります。値が再びポインターとして使用される場合、それは極端にの悪いアイデアであることが証明されます。