[Obj-C++] 06 非Xib環境にAppDelegate導入 その2

[M1 Mac, Big Sur 11.6.5, clang 13.0.0, no Xcode]

[Obj-C++] 04で作成したAppDelegate導入環境とこれまで開発してきたコードを合体させました。画面遷移がないのでViewControllerは必要ないみたいです。

当面の目標であるDrag & Drop実装への土台が出来上がりました。

#import "AppDelegate.h"
#import "XlsxConvertor.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (void)applicationWillFinishLaunching:(NSNotification*)notification {
    [[[[window alloc] init] autorelease] makeMainWindow];

}

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
    // Insert code here to initialize your application
}


- (void)applicationWillTerminate:(NSNotification *)notification {
    // Insert code here to tear down your application
}


- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
    return YES;
}

@end
#import "AppDelegate.h"

int main(int argc, const char * argv[]) {
    auto app = [NSApplication sharedApplication];
    app.delegate = [AppDelegate new];
    [app run];
}

[Obj-C++] 05 CMakeLists.txtをワイルドカードで作成

[M1 Mac, Big Sur 11.6.5, clang 13.0.0, no Xcode]

CMakeLists.txtをワイルドカードを使って作成しました。これでファイルが増えても追記不要です。

cmake_minimum_required(VERSION 3.1)

# Project
Project(XlsxConvertor VERSION 1.0.0)
find_library(COREFOUNDATION CoreFoundation)
find_library(COCOA Cocoa)

# C++11指定
set(CMAKE_CXX_STANDARD 11)

# コマンド表示
set(CMAKE_VERBOSE_MAKEFILE ON)

# Info.plist
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "Copyright (C) 2022")
set(MACOSX_BUNDLE_INFO_STRING "Convert tool for XLSX")

# ファイル設定(ワイルドカードを使用)
file(GLOB SOURCE ./src/*.mm ./include/*.h)

add_executable(${PROJECT_NAME}
    MACOSX_BUNDLE
    ${SOURCE}
    )

set(INCDIR ./include)
set(INCDIR ${INCDIR} /Library/Frameworks/Python.framework/Versions/3.10/include/python3.10)
include_directories(${INCDIR})

set(LIBS dl)
set(LIBS ${LIBS} /Library/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib)

set(LIBDIR /Library/Frameworks/Python.framework/Versions/3.10/lib)
link_directories(${LIBDIR})

target_link_libraries(${PROJECT_NAME}
    ${COREFOUNDATION}
    ${COCOA}
    ${LIBS})

[Obj-C++] 04 非Xib環境にAppDelegate導入 その1

[M1 Mac, Big Sur 11.6.5, clang 13.0.0, no Xcode]

これまで非Xcode非Xib環境で開発を進めていますが、Drag & Dropを実装するに際しライフサイクルの概念を取り入れるためAppDelegateを導入しました。IDEを使わずGUIをコードで書く非Xcode非Xib環境は継続になります。

手順は以下の通りです。最初だけXcodeを使います。

1.XcodeでmacOS – Xib – Objective-Cの空プロジェクトを作成する。
2.main.m, AppDelegate.m, AppDelegate.hを用意しておいたプロジェクトにコピーする。
3.拡張子をmからmmに書き換えて、以下の様にコードを追記する。

#import "AppDelegate.h"

@interface AppDelegate ()

@property (strong) NSWindow *window;

@end

@implementation AppDelegate

- (void)applicationWillFinishLaunching:(NSNotification*)notification {
    self.window = [[[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 300, 200)
                    styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable
                    backing: NSBackingStoreBuffered
                    defer: NO]
                    autorelease];
    auto app_name = [[NSProcessInfo processInfo] processName];
    [self.window setTitle: app_name];
    [self.window makeKeyAndOrderFront: self];
    [self.window orderFront:self];
    [self.window makeMainWindow];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
}


- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}


- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
    return YES;
}

@end
#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>

@end
#import "AppDelegate.h"

int main(int argc, const char * argv[]) {
    auto app = [NSApplication sharedApplication];
    app.delegate = [AppDelegate new];
    [app run];
}

参考サイト

[Obj-C++] 03 クラスの拡張

[M1 Mac, Big Sur 11.6.5, clang 13.0.0, no Xcode]

クラスを継承するとクラス名が変わりますが、拡張するとクラス名はそのままです。

NSTextViewクラスにappendStringメソッドを追加してみました。

なかなか便利な機能です。

#include <Cocoa/Cocoa.h>

@interface NSTextView (Controller)

-(void) appendString: (NSString *)str;

@end
#include <Cocoa/Cocoa.h>
#include "NSTextViewEx.h"

@implementation NSTextView (Controller)

-(void)appendString:(NSString *)str {
    <メソッドの内容は作成中>
    NSLog(@"%@",str);
}
@end

[Obj-C++] 02 Makefileの改良 : mmファイル追加への対応

[M1 Mac, Big Sur 11.6.5, clang 13.0.0, no Xcode]

mmファイルが増えてもMakefileに追記しなくてもいいように改良しました。

make allコマンドでappファイルを作成し、make all2では実行ファイルを作成します。LLDBでデバッグする際は実行ファイルを作成しています。

CMakeLists.txtのadd_executableのところもワイルドカードで追記不要にしたいところです。

# コンパイラ
COMPILER = clang++
DEBUG = -g

# オプション
CFLAGS = $(shell python3-config --includes)
LDFLAGS = $(shell python3-config --ldflags) -framework Cocoa

# includeパス(-I)
INCLUDE = -I./include -I/Library/Frameworks/Python.framework/Versions/3.10/include/python3.10

# ライブラリパス(-l)
LIBRARY0 = -lpython3.10

# 優先ライブラリパス(-L)
LIBRARY = -L/Library/Frameworks/Python.framework/Versions/3.10/lib

# ソースファイル
SRCDIR = ./src
SRCS = $(shell find $(SRCDIR) -type f)

# オブジェクトファイル
OBJDIR = ./obj
OBJS   = $(addprefix $(OBJDIR), $(patsubst ./src%,%,$(SRCS:.mm=.o)))

# 実行ファイル
TARGETDIR = ./bin
TARGET = XlsxConvertor

# コンパイル
$(OBJDIR)/%.o: $(SRCDIR)/%.mm
	$(COMPILER) $(CFLAGS) $(INCLUDE) $(DEBUG) -o $@ -c $<

# ビルド
$(TARGET):$(OBJS)
	$(COMPILER) -o $(TARGETDIR)/$@ $(OBJS) $(LDFLAGS) $(LIBRARY0) $(LIBRARY)

# ファイル削除
.PHONY : clean
clean:
	rm -rf $(OBJS) $(TARGETDIR)/$(TARGET)

# CMakeを経てappファイル作成
.PHONY : all
all:
	rm -rf build/*
	cd /projects/XlsxConvertor/build && cmake .. && make
	mkdir ./build/$(TARGET).app/Contents/Resources
	cp ./images/XlsxConvertor.icns ./build/$(TARGET).app/Contents/Resources
	plutil -replace 'CFBundleIconFile' -string "XlsxConvertor.icns" ./build/$(TARGET).app/Contents/Info.plist

# 実行ファイルのみ作成
.PHONY : all2
all2: clean $(TARGET)
cmake_minimum_required(VERSION 3.1)

# Project
Project(XlsxConvertor VERSION 1.0.0)
find_library(COREFOUNDATION CoreFoundation)
find_library(COCOA Cocoa)

# コマンド表示
set(CMAKE_VERBOSE_MAKEFILE ON)

# Info.plist
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "Copyright (C) 2022")
set(MACOSX_BUNDLE_INFO_STRING "Convert tool for XLSX")

# XlsxConvertor
add_executable(${PROJECT_NAME}
    MACOSX_BUNDLE
    ./src/XlsxConvertor.mm
    ./src/process.mm
    ./include/process.h
    )

set(INCDIR ./include)
set(INCDIR ${INCDIR} /Library/Frameworks/Python.framework/Versions/3.10/include/python3.10)
include_directories(${INCDIR})

set(LIBS dl)
set(LIBS ${LIBS} /Library/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib)

set(LIBDIR /Library/Frameworks/Python.framework/Versions/3.10/lib)
link_directories(${LIBDIR})

target_link_libraries(${PROJECT_NAME}
    ${COREFOUNDATION}
    ${COCOA}
    ${LIBS})

[Obj-C++] 01 Objective-C++への移行

[M1 Mac, Big Sur 11.6.5, clang 13.0.0, no Xcode]

C++の機能も使えるようにするため、Objective-CからObjective-C++へ移行します。

mファイルの拡張子をmmに変えるだけでOKです。coutで動作確認しました。

#include <Cocoa/Cocoa.h>
#include <iostream>

using std::cout; using std::endl;

int num = 1;

// Objective-C++
NSLog(@"Objective-C++ num %d",num);

// C++
cout << "C++ num " << num << endl;

--------------------------------------------------
出力
--------------------------------------------------
Objective-C++ num 1
C++ num 1

[C++] 65 FLTK : xlsx変換アプリ / MakefileからCMakeLists.txtへの移植

[M1 Mac, Big Sur 11.6.5, FLTK 1.3.8]

自製Makefileの生成するコマンドを見ながらCMakeLists.txtへ移植しました。

CMakeが作成したMakefileが生成するコマンドについては以下の行を追記して内容を確認できます。

set(CMAKE_VERBOSE_MAKEFILE ON)

Objective-Cのappファイルと同様、こちらもボタンを押下してもクラッシュしませんでした。自製Makefileではできない補完をしているのでしょう。

C++でappファイルに問題がないとなるとObjective-Cに戻って開発を進める必要がありません。

Cocoaアプリの統一感のある洗練された外観も捨てがたいので何か別のアプリで再チャレンジしたいところです。

cmake_minimum_required(VERSION 3.1)

# Project
Project(XlsxConvertor VERSION 1.0.0)
FIND_PACKAGE(FLTK REQUIRED)
FIND_PACKAGE(OpenGL REQUIRED)
find_library(COCOA Cocoa)

set(CMAKE_CXX_STANDARD 11)

# make時の生成コマンドをターミナルに表示する(デフォルトでは非表示)
set(CMAKE_VERBOSE_MAKEFILE ON)

# Info.plist
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "Copyright (C) 2022")
set(MACOSX_BUNDLE_INFO_STRING "Convert tool for XLSX")

# XlsxConvertor
add_executable(${PROJECT_NAME}
    MACOSX_BUNDLE
    ./src/XlsxConvertor.cpp
    ./src/process.cpp
    ./src/modalDialog.cpp
    ./include/process.h
    ./include/modalDialog.h
    )

set(INCDIR /include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/libpng/1.6.37/include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/fltk/1.3.8/include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/jpeg/9e/include)
set(INCDIR ${INCDIR} /Library/Frameworks/Python.framework/Versions/3.10/include/python3.10)
include_directories(${INCDIR})

set(LIBS dl)
set(LIBS ${LIBS} z pthread c++)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_forms.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_gl.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_images.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/jpeg/9e/lib/libjpeg.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/libpng/1.6.37/lib/libpng.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk.dylib)
set(LIBS ${LIBS} /Library/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib)

set(LIBDIR /opt/homebrew/Cellar/jpeg/9e/lib)
set(LIBDIR ${LIBDIR} /opt/homebrew/Cellar/libpng/1.6.37/lib)
set(LIBDIR ${LIBDIR} /opt/homebrew/Cellar/fltk/1.3.8/lib)
set(LIBDIR ${LIBDIR} /usr/local/lib /Library/Frameworks/Python.framework/Versions/3.10/lib)
link_directories(${LIBDIR})

target_link_libraries(${PROJECT_NAME}
    ${FLTK}
    ${OpenGL}
    ${LIBS}
    ${COCOA})

[C++] 64 FLTK : ドラッグ&ドロップ

[M1 Mac, Big Sur 11.6.5, FLTK 1.3.8]

Objective-Cのドラッグ&ドロップが今の私にはあまりにも難解なので、FLTKではどうやって実装していたか振り返ります。かなり簡単に実装できます。

FL_Boxでファイルをドロップする領域を指定し、ドロップされたファイルの情報をFL_Boxの引数で指定したFL_Inputに渡します。単純明快です。

Objective-Cのドラッグ&ドロップについては必須ではなく努力目標にして、FLTKアプリのCMakeLists.txt作成に優先して取り組むことにします。

同じ内容の実装でもC++(FLTK)とObjective-Cでこれだけ難易度が違うと難しい方を学ぼうとする気力がなかなかわきません。

Xcodeで書けばいいのですが、xibファイルやStoryboardを扱いたくないのでモチベが上がらないです。

<該当箇所のみ>

class Box : Fl_Box {
    Fl_Input* input_line2;

    public:
        Box(int, int, int, int, Fl_Input*);
    private:
        auto handle(int) -> int override;
};

Box::Box(int x, int y, int width_input, int height_input, Fl_Input* input) : 
    Fl_Box(FL_NO_BOX, x, y, width_input, height_input, "") {
    this->input_line2 = input;
    }

auto Box::handle(int event) -> int {
    switch (event) {
        case FL_DND_DRAG:
        case FL_DND_ENTER:
        case FL_DND_RELEASE:
            return 1;

        case FL_PASTE:
            input_line2->value(Fl::event_text());
            input_line2->textsize(12);
            input_line2->textfont(FL_HELVETICA);

            return 1;

        default:
            return Fl_Box::handle(event);
    }
}

int main(int argc, char **argv) {
    Box *box = new Box(0, 0, 360,220, input_line);
}

[Obj-C] 16 GUIアプリ : MakefileをCMakeLists.txtへ移植

[M1 Mac, Big Sur 11.6.5, no Xcode]

MakefileをCMakeLists.txtへ移植しました。

CMakeが作成したMakefileがどういったコマンドを実行しているのか分からないので気が進まなかったのですが、非XCode環境で開発を進めるにはどうも避けられないためやむなく着手しました。

自製Makefileでは認識していた -lpython3.10がリンク時に見つからないというエラーへの対策でだいぶ時間を取られました。出力をよく読むとビルドの時にはちゃんと認識していたので、そのライブラリパスをtarget_link_librariesのところに書いたらうまくいきました。CMakeは案外融通の効かないところがあるようです。

いちいちbuildディレクトリに潜るのは面倒なのでプロジェクトフォルダのルートからMakefileでCMakeを実行するというちょっとややこしいけど楽なやり方で進めています。make allコマンド一発でCMakeを経てappファイルまで作ってくれます。

自製Makefileで作成したappファイルはボタン押下時に落ちてしまいましたが、今回のappファイルはクラッシュしません。これは全く期待していなかったのでうれしい限りです。

C++からわざわざObjective-Cへ移植したかいがありました。

ビルド時に-lpython3.10を認識しているが、リンク形成ではエラーになる。
cmake_minimum_required(VERSION 3.1)

# Project
Project(XlsxConvertor VERSION 1.0.0)
find_library(COREFOUNDATION CoreFoundation)
find_library(COCOA Cocoa)

# Info.plist
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "Copyright (C) 2022")
set(MACOSX_BUNDLE_INFO_STRING "Convert tool for XLSX")

# XlsxConvertor
add_executable(${PROJECT_NAME}
    MACOSX_BUNDLE
    ./src/XlsxConvertor.m
    ./src/process.m
    ./include/process.h)

set(INCDIR ./include)
set(INCDIR ${INCDIR} /Library/Frameworks/Python.framework/Versions/3.10/include/python3.10)
include_directories(${INCDIR})

set(LIBDIR /Library/Frameworks/Python.framework/Versions/3.10/lib)
link_directories(${LIBDIR})

set(LIBS dl)
set(LIBS ${LIBS} /Library/Frameworks/Python.framework/Versions/3.10/lib/libpython3.10.dylib)

target_link_libraries(${PROJECT_NAME}
    ${COREFOUNDATION}
    ${COCOA}
    ${LIBS})
# CMakeを経てappファイル作成(アイコン登録含む)

TARGET = XlsxConvertor

.PHONY : all
all:
	rm -rf build/*
	cd /projects/XlsxConvertor09/build && cmake .. && make
	mkdir ./build/$(TARGET).app/Contents/Resources
	cp ./images/XlsxConvertor.icns ./build/$(TARGET).app/Contents/Resources
	plutil -replace 'CFBundleIconFile' -string "XlsxConvertor.icns" ./build/$(TARGET).app/Contents/Info.plist