Androidサンプル ローカルにファイルを保存する
Androidでローカルにファイルを保存する方法についてです。
ファイル書き込みを許可する
ファイルアクセスを許可するため、AndroidManifest.xmlに以下のタグを追加します。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
ディレクトリを作成する
ローカルにファイルを保存したい場合、アクセスできる場所が限られていまして、
/data/data//files
にしかファイル入出力はできないようです。
例えば、パッケージ名がcom.java.yourdomainなら
/data/data/com.java.yourdomain/files
となります。パッケージ名はContextクラスのgetPackageNameで得られます。(ちなみにActivityはContextを継承している)
String path = "/data/data/" + context_.getPackageName() + "/files"; File file = new File(path); file.mkdir();
ファイルを作成する
FileOutputStreamを使います。(例外処理省略)
public boolean writeFile(String fileName) throws IOException { FileOutputStream fileOutputStream = context_.openFileOutput(fileName, Context.MODE_PRIVATE); String buffer = "12345"; fileOutputStream.write(buffer.getBytes()); return true; }
ファイルを読み込む
同様にFileInputStreamを使います。
public boolean readFile(String fileName) throws IOException { FileInputStream fileInputStream = context_.openFileInput(fileName); byte[] buffer = new byte[5]; fileInputStream.read(buffer, 0, 5); String string = new String(buffer); }
Xcode4の使い方メモ 〜 ターゲットを作る
Xcodeではプロジェクト1つに対して複数のターゲットを追加できるみたいなので、自前makefileを使ってビルドできるようにしてみます。
まずC++のCommandLineToolプロジェクト"Multiple_targets"を作成しておきます。→/
ターゲットを追加する
File>New>New Target>Other>External Build System>ターゲット名"SecondTarget"
Product>Edit Scheme>Build>"+">新規作成したターゲット名"SecondTarget">"Add"でターゲットが追加されます。
makefileを指定するにはTARGETS>"SecondTarget">Info>Directoryにmakeを実行するディレクトリを入力します。
(例えばmakefileの場所が/
main.cppはそのままにして、makefileを用意します。
CXX = g++ TARGET=test_program SRCS= main.cpp OBJS= main.o RM= rm -f $(TARGET): $(OBJS) $(CXX) -o $(TARGET) $(OBJS) $(RM) $(OBJS) .cpp.o: $(CXX) -c $< -o $@ clean: $(RM) $(TARGET) $(OBJS)
ビルドしてみるとtest_programが作成されます。実行してコンソールにHelloWorldが出力されていればOK.
新しいスキームを作成する
デフォルトでは既存のスキームが適用されていますので、新規のスキームを作ってみます。
Project>New Scheme>Second Target>OK
Run Test>Info>Executable>test_programを選択。
これでRunボタンを押すとtest_programが実行され、コンソールにHelloWorldが出力されます。また、ProfileやAnalyzeも同様に設定することができます。
iOSで静的ライブラリを使う
Objective-CとC++の両方を混在させてみます。※(注)環境はiOS SDK4.3, Xcode4.1, 動作確認はシミュレータのみ
Static Library用プロジェクトを作成する
File>New>NewProject>iOS>Framework & Libraries>CocoaTouch>StaticLib.xcodeprojを/
→/
/
test.h
#ifndef _test_h #define _test_h class Sample{ public: void test(); }; #endif
test.cpp
#include "test.h" #include <stdio.h> void Sample::test(){ printf("Sample::test was called\n"); }
C++を記述するソースの拡張子を.mmに修正、C++で記述されたヘッダをインクルードしているObjective-Cのヘッダを.hhに修正します。
StaticLib.h→StaticLib.hhにする
#import <Foundation/Foundation.h> @interface StaticLib : NSObject -(void)test; @end
StaticLib.m→StaticLib.mmにする
#import "StaticLib.hh" #import "test.h" @implementation StaticLib - (id)init { self = [super init]; if (self) { } return self; } -(void)test { NSLog(@"[StaticLib test] was called\n"); Sample sample; sample.test(); } @end
ビルドするとlibStaticLib.aが作成されます。
ライブラリを使用するプロジェクトを作成する
File>New>NewProject>iOS>Applications>適当に選択>StaticLibUse.xcodeprojを作成
→/
File>Add Files to "StaticLibUse.xcodeproj"> StaticLib.xcodeprojのパスを選択>Add
StaticLibUse.xcodeprojに入れ子状にStaticLib.xcodeprojが追加される
StaticLibUse.xcodeprojのTARGET>Build Phases>Link Binary With Libaries>"+">libStaticLib.a>Doneでライブラリを追加
同様にTarget Dependency>"+">StaticLibでプロジェクトの依存関係を追加
Edit Scheme>Build>"+">StaticLibでビルド対象となるターゲットStaticLibを追加
StaticLibUse.xcodeprojからtest.h,StaticLib.hを読み込むためにインクルードパスを設定します。例えば"/
StaticLibUse.xcodeproj選択>TARGET>Build Settings>Serach Headers>"+">ヘッダパス入力 再帰検索ならRecursiveにチェック>Done
ライブラリを使用する
C++を使うので同様にStaticLibUseAppDelegate.mの拡張子をmmに変更しておきます。
StaticLibUseAppDelegate.mm
#import "StaticLibUseAppDelegate.h" // その他デフォルトのヘッダ→略 // ライブラリのヘッダインクルード #import "test.h" #import "StaticLib.h" @implementation StaticLibUseAppDelegate // メンバ、メソッド定義→略 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { Sample sample; sample.test(); StaticLib* staticLib = [[StaticLib alloc]init]; [staticLib test]; [staticLib release]; // 略 return YES; }
以上で、Objective-CとC++の両方のIFを呼び出すことができます。実行して両方とも呼び出されれば成功です。
Sample::test was called [StaticLib test] was called Sample::test was called
FreeType2をインストールして使ってみる
OSXでfreetypeを使った手順について。
※環境はMacOSX10.7、freetype2.4.6です。他にbzip2-v1.0.6、zlib1.2.5も用意しておきます。
※ビルドした静的ライブラリをインストールせずに持ち運んで使ってみます
freetype2のビルド
http://freetype.sourceforge.net/index2.htmlからDownloads stable release を選択>
http://sourceforge.net/projects/freetype/files/からfreetype-2.4.6.tar.bz2をダウンロードして展開します。展開したディレクトリに移動してターミナルで以下のコマンドを実行
./configure make
objs/.libs/libfreetype.a、libfreetype.6.dylibが作成されています。
Xcodeで利用する
C++のCommandLineToolsプロジェクトを作成します。(例えば/
ライブラリとヘッダをコピーします。
/
/
/
Link Binary With Librariresでlibfreetype.aをプロジェクトに追加
Search Paths>Search Header PathとLibrary Pathでインクルードパスとライブラリパスをプロジェクトに追加
この時点でmain.cppで適当に関数を呼んでビルドすると、以下のようなリンクエラーになります。
Undefined symbols for architecture x86_64: "_inflateInit2_", referenced from: _FT_Stream_OpenGzip in libfreetype.a(ftgzip.o) "_inflateEnd", referenced from: _FT_Stream_OpenGzip in libfreetype.a(ftgzip.o) _ft_gzip_stream_close in libfreetype.a(ftgzip.o) "_inflate", referenced from: _ft_gzip_file_fill_output in libfreetype.a(ftgzip.o) "_inflateReset", referenced from: _ft_gzip_file_io in libfreetype.a(ftgzip.o) "_BZ2_bzDecompressInit", referenced from: _FT_Stream_OpenBzip2 in libfreetype.a(ftbzip2.o) _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o) "_BZ2_bzDecompressEnd", referenced from: _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o) _ft_bzip2_stream_close in libfreetype.a(ftbzip2.o) "_BZ2_bzDecompress", referenced from: _ft_bzip2_file_fill_output in libfreetype.a(ftbzip2.o) ld: symbol(s) not found for architecture x86_64
zlibが足りないので、ビルドして作成したlibz.aを/
"_BZ2_bzDecompressInit", referenced from: _FT_Stream_OpenBzip2 in libfreetype.a(ftbzip2.o) _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o) "_BZ2_bzDecompressEnd", referenced from: _ft_bzip2_stream_io in libfreetype.a(ftbzip2.o) _ft_bzip2_stream_close in libfreetype.a(ftbzip2.o) "_BZ2_bzDecompress", referenced from: _ft_bzip2_file_fill_output in libfreetype.a(ftbzip2.o) ld: symbol(s) not found for architecture x86_64
libbzip2.aをビルドして、Link Binary With Librariesでターゲットに追加
さらに/
これでエラーがなくなります。
FreeType2を使ってみる
正確な情報はこちらを参照してください。↓
http://freetype.sourceforge.net/freetype2/docs/tutorial/step1.html
ヘッダのインクルード
下の2つのヘッダをインクルードします。(FT_FREETYPE_Hはヘッダのパスを定義したマクロ)
#include <ft2build.h> #include FT_FREETYPE_H
初期化
ライブラリを表すFT_Libraryオブジェクトに対してFT_Init_FreeTypeを実行します。ここではFT_Libraryをグローバルに保持しておきます。FreetypeのAPIはFT_Error型のエラーコードがかえってきます。エラーが無い場合はFT_Err_Okです。
FT_Library s_library;
int main{
FT_Error error = FT_Init_FreeType( &s_library );
フォント読み込み
適当なフォントを用意しておいて、FT_New_Faceを実行します。引数にFT_Face型のfaceオブジェクトを渡します。こちらもグローバルに定義しておきます。
FT_Face s_face int main(){ // 略 error = FT_New_Face( s_library, "/yourFontPath/MyFavoriteFont.ttf", 0, &s_face );
※フォントの場所はOSXのバージョンによって異なる。v10.7では/Libary/Fonts内にあります。
文字サイズを設定する
error = FT_Set_Char_Size( s_face, 0, 16*64, // 幅と高さ 300, // 水平解像度 300 ); // 垂直解像度
字体を作成する
まずFT_Get_Char_Indexでアスキーコードに対応する字体番号を取得します。文字が用意されていないなら0がかえります。この番号を渡してFT_Load_Glyphを呼ぶと実際に字体が取得されます。取得した字体をレンダリングするにはFT_Render_Glyphを呼び出します。これで内部にレンダリングされたビットマップが作成されています。ちなみに字体の各パラメータはFT_Face構造体のglyphメンバ(FT_GlyphSlot型)に保存されます。
glyph_index = FT_Get_Char_Index( s_face, 'q' );
error = FT_Load_Glyph( s_face, glyph_index, FT_LOAD_DEFAULT );
FT_GlyphSlot slot = s_face->glyph;
error = FT_Render_Glyph( slot, FT_RENDER_MODE_NORMAL );
リンダリングの種類を選ぶこともできます。(FT_RENDER_MODE_NORMALはRGB, FT_RENDER_MODE_MONOが2値画像など)
ビットマップを取り出す
FT_GlyphSlotのbitmapメンバ(FT_Bitmap型)でビットマップを取り出します。FT_Bitmapのbufferメンバがバッファのアドレスになります。
FT_GlyphSlot slot = s_face->glyph; if( slot->format != FT_GLYPH_FORMAT_BITMAP ) // error FT_Bitmap bitmap = slot->bitmap; // ビットマップの情報を取り出す width = bitmap.width; height = bitmap.rows; rawData = bitmap.buffer;
あとは画像データを出力したりテクスチャに利用することができます。
グリフの情報を取り出す
描画位置の補正値やペンの動きなども取得できます。
FT_GlyphSlot slot = s_face->glyph; slot->bitmap_left; // x + slot->bitmap_left , y + slot->bitmap_topに描画すればOK slot->bitmap_top; // int advanceX = slot->advance.x >> 6; // x方向にペンを動かすべき距離 int advanceY = slot->advance.y >> 6; // y方向にペンを動かすべき距離
※その他、追記するかもしれません
OpenGLサンプル テクスチャ
OpenGLでテクスチャを表示する手順です。複数枚でブレンディングを有効にして表示してみます。
画像を読み込む
代表的な読み込み方は
・ライブラリを利用して直接読み込む( OpenCVのcvLoad, linpng, libjpgなど。または自作するなど)
・フレームワーク付属のクラスを利用してraw dataを取り出す。
ここでは読み込んだと仮定して、画像を自動生成することにします。
画像のデータをまとめてグローバルに定義しておきます。
static const int RGB = 3; static const int RGBA = 4; struct image_t{ int width; int height; int channels; void*buffer; ~image_t(){ if(buffer)::free(buffer); } }; image_t image1 = {64, 64, RGB, 0}; image_t image2 = {64, 64, RGBA, 0}; // ブレンディング対象
画像の読み込みの代わりの関数を作成します。左上端に目印を付けて表示が正しいか判断することにします。画像データの配列は、R,G,BあるいはR,G,B,Aの順で作成します。読み込むときも同様なので、BGR型の配列を読み込んだときは順序を変換しないといけません。
void *loadTexture(int width, int height, int channels, const char* filePathDummy){ // 画像を読み込む(ここでは仮として自動生成する) typedef unsigned char* iterator_t; int image_size = width * height * channels * sizeof(unsigned char); void *image = ::malloc( image_size ); // nullチェック略 iterator_t itr_dest = iterator_t(image); iterator_t itr_dest_end = itr_dest + image_size; // ストライプ作成 int pixel = 0; int stride = 3; while (itr_dest != itr_dest_end) { *itr_dest++ = 255-50 * pixel ; *itr_dest++ = 255-50 * pixel ; *itr_dest++ = 255-10 * pixel ; if (channels == RGBA) { *itr_dest++ = 100; // 半透明 } pixel = ++pixel % stride; } // 上左端に目印をつける itr_dest = iterator_t(image); for(int i = 0 ; i < width / 3; i++){ *itr_dest++ = 50; // cyan *itr_dest++ = 255; *itr_dest++ = 255; if (channels == RGBA) { *itr_dest++ = 100; } } return image; }
int main(int argc, char **argv){ //略 // load image data image1.buffer = loadTexture(image1.width, image1.height, image1.channels, "icon1.png"); image2.buffer = loadTexture(image2.width, image2.height, image2.channels, "icon2.png");
テクスチャの管理
各テクスチャはGLuint型の番号で管理します。複数枚のときはGLuint型の配列を用意しておきます。こちらも画像とセットでグローバルに定義しておきます。
const int TEXTURES = 2; GLuint textureArray[TEXTURES];
テクスチャ領域の確保と解放
glGenTextures・glDeleteTexturesを使います。
int main(int argc, char **argv){ //略... glEnable(GL_TEXTURE_2D); glGenTextures( TEXTURES, textureArray ); // ... } void onExit(){ glDeleteTextures(TEXTURES, textureArray); glDisable(GL_TEXTURE_2D); }
先ほどの配列と対応した領域が内部に作成されます。今後特定のテクスチャを指定するときはGLuint型の番号textureArray[i]を用います。特定のテクスチャに関する処理を実行するときも引数にGLuint型の番号を入れます。
テクスチャの作成
glBindTextureで現在のテクスチャを指定、glPixelStorei、glTexParameterf、glTexEnviなどでテクスチャの各パラメータを指定、glTexImage2Dで画像からテクスチャを作成します。glTexImage2Dのの引数formatには内部フォーマットを、次の引数formatには画像のフォーマットを指定します。ブレンド処理に対応させるときは双方にGL_RGBAを入れておきます。
void textureFromImage(GLuint textureId, image_t* image){ // IDによって現在のテクスチャを指定する glBindTexture(GL_TEXTURE_2D, textureId ); // パラメータ設定(例) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); // texture environment glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // 画像からテクスチャ作成 GLenum format = GL_RGB; if(image->channels == RGBA){ format = GL_RGBA; // 4channelのときはGL_RGBAを引数にする } glTexImage2D(GL_TEXTURE_2D, 0, format, image->width, image->height, 0, format, GL_UNSIGNED_BYTE, image->buffer ); }
テクスチャの描画
glVertexPointerで描画位置を指定、glTexCoordPointerでテクスチャマッピング座標を指定します。その後にglDrawArraysで描画します。テクスチャマッピングを行う前に、glBindTextureでどのテクスチャに適用するのか指定しておきます。
void drawTexture(GLuint textureId, float x, float y, float width, float height ){ static const int VERTEX_DIMENSION = 2; static const int NUM_VERTICES = 4; // 描画位置 float vertexArray[ ] = { x, y, // 左下 x + width, y, // 右下 x, y + height, // 左上 x + width, y + height // 右上 }; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer( VERTEX_DIMENSION, GL_FLOAT, 0, vertexArray ); // texture mapping座標 static const float textureCoordArray[] = { 0.0f, 1.0f, // 左下 1.0f, 1.0f, // 右下 0.0f, 0.0f, // 左上 1.0f, 0.0f, // 右上 }; glEnable(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindTexture(GL_TEXTURE_2D, textureId ); glTexCoordPointer(2, GL_FLOAT, 0, textureCoordArray); // 描画 glDrawArrays(GL_TRIANGLE_STRIP, 0, NUM_VERTICES); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); }
ブレンディングの設定
ブレンディングの種類を予め指定しておきます。
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
以上で、画像1はそのまま、画像2が半透明で描画されます。
(参考)サンプル全体のコード。
#include <stdlib.h> #include <GLUT/glut.h> // OSX上で実行 // テクスチャ const int TEXTURES = 2; GLuint textureArray[TEXTURES]; // 画像 static const int RGB = 3; static const int RGBA = 4; struct image_t{ int width; int height; int channels; void*buffer; ~image_t(){ if(buffer){ ::free(buffer);} } }; image_t image1 = {64, 64, RGB, 0}; image_t image2 = {64, 64, RGBA, 0}; // ブレンディング対象 // 関数 void *loadTexture(int width, int height, int channels, const char* filePath = ""); void drawTexture(GLuint textureId, float x, float y, float width, float height ); void textureFromImage(GLuint textureId, image_t* image); void drawScene(); void onExit(); int main(int argc, char **argv){ glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); glutInitWindowSize(500, 500); glutCreateWindow( "glut window" ); glutDisplayFunc( drawScene ); ::atexit(onExit); // init openGL glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // load image data image1.buffer = loadTexture(image1.width, image1.height, image1.channels, "icon1.png"); image2.buffer = loadTexture(image2.width, image2.height, image2.channels, "icon2.png"); // generate textures glEnable(GL_TEXTURE_2D); glGenTextures( TEXTURES, textureArray ); // convert image to texture GLuint textureID1 = textureArray[0]; GLuint textureID2 = textureArray[1]; textureFromImage(textureID1, &image1); textureFromImage(textureID2, &image2); glutMainLoop(); return 0; } void onExit(){ glDeleteTextures(TEXTURES, textureArray); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); } // 描画 void drawScene(){ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f); glClear( GL_COLOR_BUFFER_BIT ); // draw textues GLuint textureID1 = textureArray[0]; GLuint textureID2 = textureArray[1]; drawTexture(textureID1, 0.1f, 0.1f, 0.2f, 0.2f); drawTexture(textureID2, -0.3f, -0.3f, 0.5f, 0.5f); glutSwapBuffers(); } // テクスチャ描画 void drawTexture(GLuint textureId, float x, float y, float width, float height ){ static const int VERTEX_DIMENSION = 2; static const int NUM_VERTICES = 4; // 描画位置 float vertexArray[ ] = { x, y, // 左下 x + width, y, // 右下 x, y + height, // 左上 x + width, y + height // 右上 }; glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer( VERTEX_DIMENSION, GL_FLOAT, 0, vertexArray ); // texture mapping座標 static const float textureCoordArray[] = { 0.0f, 1.0f, // 左下 1.0f, 1.0f, // 右下 0.0f, 0.0f, // 左上 1.0f, 0.0f, // 右上 }; glEnable(GL_TEXTURE_2D); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindTexture(GL_TEXTURE_2D, textureId ); glTexCoordPointer(2, GL_FLOAT, 0, textureCoordArray); // 描画 glDrawArrays(GL_TRIANGLE_STRIP, 0, NUM_VERTICES); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } void textureFromImage(GLuint textureId, image_t* image){ // IDによって現在のテクスチャを指定する glBindTexture(GL_TEXTURE_2D, textureId ); // パラメータ設定(例) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // 画像からテクスチャ作成 GLenum format = GL_RGB; if(image->channels == RGBA){ format = GL_RGBA; // 4channelのときはGL_RGBAを引数にする } glTexImage2D(GL_TEXTURE_2D, 0, format, image->width, image->height, 0, format, GL_UNSIGNED_BYTE, image->buffer ); } // 画像を読み込む(ここでは仮として自動生成する) void *loadTexture(int width, int height, int channels, const char* filePathDummy){ typedef unsigned char* iterator_t; int image_size = width * height * channels * sizeof(unsigned char); void *image = ::malloc( image_size ); // nullチェック略 iterator_t itr_dest = iterator_t(image); iterator_t itr_dest_end = itr_dest + image_size; // ストライプ作成 int pixel = 0; int stride = 3; while (itr_dest != itr_dest_end) { *itr_dest++ = 255-50 * pixel ; // r *itr_dest++ = 255-50 * pixel ; // g *itr_dest++ = 255-10 * pixel ; // b if (channels == RGBA) { *itr_dest++ = 100; // a:半透明 } pixel = ++pixel % stride; } // 上左端に目印をつける itr_dest = iterator_t(image); for(int i = 0 ; i < width / 3; i++){ *itr_dest++ = 50; // cyan *itr_dest++ = 255; *itr_dest++ = 255; if (channels == RGBA) { *itr_dest++ = 100; } } return image; }
libpng1.5.4をOSXでビルドする
zlibをビルドする
http://zlib.net/からzlib source code, version 1.2.5をダウンロード、適当なディレクトリ
あとは、configure,make,make installを実行するだけです。
./configure make make install
libz.aやlibz1.2.5.dylibが作成されています。
ソースコードの入手
http://www.libpng.org/pub/png/libpng.html
バージョン1.5.4の表のSource code:から入手→適当なディレクトリ
cd
次にconfigureを呼び出しますが、"./configure"を走らせようとしても動きません→autogen.shを先に呼び出して回避します。
./configure --enable-maintainer-mode make maintainer-clean ./autogen.sh
ところがautogen.shを走らせようとすると下のエラーがでます。
running libtoolize ./autogen.sh: line 15: libtoolize: command not found ERROR: autogen.sh failed, autogen is incomplete
libtoolizeがないとのこと。libtoolize→glibtoolizeに書き換えて実行すればうまくいきます。
autogen.sh
LT=${LIBTOOLIZE-libtoolize}
↓
LT=${LIBTOOLIZE-glibtoolize}
autogen.shを実行します。
$ ./autogen.sh running glibtoolize running aclocal running autoheader [ignore the warnings] running automake configure.ac:39: installing `./config.sub' configure.ac:22: installing `./missing' configure.ac:22: installing `./install-sh' configure.ac:39: installing `./config.guess' Makefile.am: installing `./depcomp' running autoconf autogen complete
あとはconfigureでmakefileを作成します。
$ ./configure checking for a BSD-compatible install... /usr/bin/install -c ....省略 .... configure: creating ./config.status config.status: creating Makefile config.status: creating libpng.pc config.status: creating libpng-config config.status: creating config.h config.status: executing depfiles commands config.status: executing libtool commands
makeします。
$make make all-am ....省略 .... libtool: link: ranlib .libs/libpng15.a libtool: link: ( cd ".libs" && rm -f "libpng15.la" && ln -s "../libpng15.la" "libpng15.la" ) cp libpng-config libpng15-config cp libpng.pc libpng15.pc
でlibpng.a、libpng15.dylibが作成されました。
インストールするには、
make install
を実行して完了です。あとはlibpng.aなどを持ち運んで利用することもできます。
Xcodeで利用する
static libraryを利用するには、libz.a, libpng.aへのライブラリパスを指定して、
TARGET>Build Settings>Search Paths>Library Search Paths
ライブラリを追加すればOKです。
Build Phases>Link Binary With Libraries>"+">Add Others>libpngとlibzを追加
Cocoaアプリでライブラリを使用する方法
CocoaアプリケーションのプロジェクトにC/C++で作成しているStaticLibraryプロジェクトやCocoaFrameworkを組み込む方法についてです。開発環境はXcode 4です。
まず実行ファイルの出力先を相対パスに設定しておきます。
Xcode>Preferences>Locations>Derived Data>Relative
StaticLibrary用プロジェクトの作成
File>New>New Project>MacOSX>Framework&Library>C/C++Library>Next>ProductNameに名称入力"StaticLibForCocoa", Type:Static>プロジェクトのパスを指定、"
/
プロジェクトにC++クラスを追加します
StaticLib.h
class StaticLib{ public: static void print(); };
StaticLib.cpp
#include "StaticLib.h" #include <stdio.h> void StaticLib::print(){ printf("Staticlib::print"); }
Cocoaアプリケーションプロジェクトの作成
File>New>New Project>MacOSX>Application>Cocoa Application>Next>ProductNameに名称入力"CocoaLibUse", Type:Static>プロジェクトのパスを指定、"
/
CocoaプロジェクトにStaticLibrary用プロジェクトを読み込ませる
File>Add Files To "CocoaLibUse">スタティックライブラリ用プロジェクトStaticLibForCocoa.xcodeprojを選択する>Add
これでCocoaLibUse.xcodeproj内にStaticLibForCocoa.xcodeprojが追加できます。
Staticライブラリ用プロジェクトのターゲットを追加する
Cocoaプロジェクトのビルドと同時にStaticライブラリ用プロジェクトもビルドされるように設定します
Product>Edit Scheme>Build>"+">StaticLibForCocoaを選択>Add
Staticライブラリ側のターゲットを追加することができました。
ライブラリを追加する
リンクするライブラリ一覧にlibStaticLibForCocoa.aを加えます。
CocoaLibUseのターゲットを選択>Build Phases>Link Binary With Libraries>"+">Workspace>"libStaticLibForCocoa.a"を選択>Add
Build Phases>TargetDependencies>"+">StaticLibForCocoaを選択>Add
Staticライブラリのヘッダインクルードパスを設定する
ヘッダStaticLib.hへのパスを通します。
CocoaLibUseのターゲットを選択>Build Settings>Search Paths>Header Search Paths>ターゲットの項目をクリック>"+">Recursiveにチェックを入れる>Pathに"../StaticLibForCocoa"を入力
Staticライブラリを利用する
ファイルをObjective-C++に対応させるために拡張子を.mmにかえます。(CocoaLibUseAppDelegate.m→CocoaLibUseAppDelegate.mmに変更)
さらにCocoaLibUse内のヘッダファイルの拡張子を.hhに変更します。
CocoaLibUseAppDelegate.h→CocoaLibUseAppDelegate.hh
(ライブラリ側のヘッダと".hh"をインルードしているobjective-cのヘッダは全て.hhに変更)
StaticLib.hをimportして、StaticLibクラスを利用します。呼び出し側のコードはC++スタイルで記述します。
CocoaLibUse.mm
#import "CocoaLibUseAppDelegate.hh" #import "StaticLib.h" @implementation CocoaLibUseAppDelegate @synthesize window; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { StaticLib::print(); } @end
最後にビルド・実行して
Staticlib::print
がコンソールに表示されれば成功です。
次にカスタムCocoaFrameworkを別プロジェクトから使用する手順です。
CocoaFrameworkプロジェクトの作成
File>New>New Project>MacOSX>Framework&Library>CocoaFramework>Next>ProductNameに名称入力"MyCocoaFramework",プロジェクトのパスを指定、"
/
プロジェクトにObjective-Cクラスを追加する
MyCocoaFramework.h
@interface MyCocoaFramework : NSObject +(void)API; @end
MyCocoaFramework.m
#import "MyCocoaFramework.h" @implementation MyCocoaFramework +(void)API { NSLog(@"MyCocoaFramework API was called."); } @end
CocoaFrameworkの利用
Cocoaプロジェクトに作成したFrameworkプロジェクトを読み込ませます。
File>Add Files To "CocoaLibUse">スタティックライブラリ用プロジェクトMyCocoaFramework.xcodeprojを選択する>Add
CocoaLibUse.xcodeproj内にMyCocoaFramework.xcodeprojが追加されます。
Staticライブラリ用プロジェクトのターゲット・ライブラリを追加する
先ほどと同様に
Product>Edit Scheme>Build>"+">MyCocoaFrameworkを選択>Add
さらに
CocoaLibUseのターゲットを選択>Build Phases>Link Binary With Libraries>"+">Workspace>"MyCocoaFramework.framework"を選択>Add
Staticライブラリのヘッダインクルードパスを設定する
CocoaLibUseのターゲットを選択>Build Settings>Search Paths>Header Search Paths>ターゲットの項目をクリック>"+">Recursiveにチェックを入れる>Pathに"../MyCocoaFramework"を入力
frameworkを利用する
CocoaLibUseAppDelegateからMyCocoaFrameworkを呼び出してみます。
CocoaLibUseAppDelegate.m
#import "CocoaLibUseAppDelegate.h" #import "MyCocoaFramework.h" @implementation CocoaLibUseAppDelegate @synthesize window; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { [MyCocoaFramework API]; } @end
最後にビルド・実行して
MyCocoaFramework API was called.
がコンソールに表示されれば成功です。