[Obj-C] 09 GUIアプリ : Python/C API用Makefile

[M1 Mac, Big Sur 11.6.5, no Xcode]

Python/C APIに対応したCMakeLists.txtの書き方が分からないので、Makefileに戻ってきました。小回りの効くところがMakefileの強みですね。

プロジェクトのファイルが増えてFinderが見にくくなったため、include、obj、src、binディレクトリを作成して配置し直しています。

Objective-Cでアプリを作れるようになったのは嬉しいですが、それよりもXcodeを起動せずにここまでやれたことの方が喜びが大きいです。

# コンパイラ
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 = $(SRCDIR)/XlsxConvertor.m $(SRCDIR)/process.m

# オブジェクトファイル
OBJDIR = ./obj
OBJS = $(OBJDIR)/XlsxConvertor.o $(OBJDIR)/process.o

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

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

$(OBJDIR)/process.o: $(SRCDIR)/process.m
	$(COMPILER) $(CFLAGS) $(INCLUDE) $(DEBUG) -o $@ -c $<

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

# ファイル削除&コンパイル
.PHONY : all
all: clean $(TARGET)

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

# CMake用
.PHONY : test
test:
	rm -rf build/*
	cd /XlsxConvertor/build && cmake .. && make

[Obj-C] 08 GUIアプリ : Python/C APIの使用

[M1 Mac, Big Sur 11.6.5, no Xcode]

C++(FLTK)からObjective-Cへの移植がほぼ完了しました。実行ファイル作成までたどり着きました。

Excelファイルを読み込み、A列のセル値をリスト化して出力する機能を実装しています。使用しているライブラリはopenpyxlです。

あてにしていたPyObjCはどうやらPythonからCocoaなどのフレームワークやライブラリを利用するという目的で作られたものであり、Python/C APIをアレンジしたものではないことが分かってきました。冷静に考えればApple系開発者がそこまでするメリットはあまりないですね。

せっかくなのでPython/C APIで実装しましたが、appファイルを作成して実行してもC++と同様に落ちてしまうでしょう。試しにC++で作成したappファイル内にある実行ファイルを入れ替えるとNGでした。

Objective-Cは細かいところになると機能の少なさを露呈するものの外観のまとまりはいいので、コンソール付きのCocoaアプリとして残りの機能も実装しようと思います。

@interface Xlsx : NSObject

- (NSString *)XlsxToList:(NSString *)path;

@end
#include <Cocoa/Cocoa.h>
#include "process.h"
#include </Library/Frameworks/Python.framework/Versions/3.10/include/python3.10/Python.h>

@implementation Xlsx

- (NSString *)XlsxToList:(NSString *)path{

    Py_Initialize();

    // pyファイルの指定
    PyObject* myModuleString = PyUnicode_FromString((char*)"test");

    // pyファイルのモジュール化
    PyObject* myModule = PyImport_Import(myModuleString);

    // pyファイル内の関数を指定
    PyObject* myFunction = PyObject_GetAttrString(myModule,(char*)"xlsx_to_list");

    // 関数の引数を設定
    PyObject* args = PyTuple_Pack(1,PyUnicode_FromString((char *) [path UTF8String]));

    // 関数を実行し戻り値をPyObjectとして取得
    PyObject* myResult = PyObject_CallObject(myFunction,args);

    // PyObjectをconst char*へ変換
    const char* result = PyUnicode_AsUTF8(myResult);

    // NSStringへ変換
    NSString* result_ns = [NSString stringWithCString: result encoding:NSUTF8StringEncoding];

    return result_ns;

    Py_FinalizeEx();    

}
@end
#include <Cocoa/Cocoa.h>
#include "process.h"

<該当箇所のみ>

- (IBAction) OnButton1Click:(id)sender {
	NSString* path = [textBox1 stringValue];

	Xlsx* test = [[Xlsx alloc] init];
	NSString* result = [test XlsxToList:path];
	[textview setString:result];
}

[Obj-C] 07 GUIアプリ : NSTextView

[M1 Mac, Big Sur 11.6.5, no Xcode]

ラジオボタンとテキストエリアを配置しました。これでGUI自体は完成です。

ラジオボタンを簡単にグループ化できない、NSTextViewの枠線を容易に描けない、など機能面では比較的簡素とされているFLTKにも及ばないという印象です。

日進月歩のC++に比較して古き良きC言語テイストを保っているという感じでしょうか。

<該当箇所のみ>

// radioButton
radioButton_a1 = [[[NSButton alloc] initWithFrame:NSMakeRect(100, 265-20-75, 60, 20)] autorelease];
[radioButton_a1 setFont:[NSFont fontWithName:@"Arial" size:12]];
[radioButton_a1 setTitle:@"LIST"];
[radioButton_a1 setButtonType:NSButtonTypeRadio];
[radioButton_a1 setTarget:self];
[radioButton_a1 setAction:@selector(OnRadioClick:)];
[radioButton_a1 setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
[radioButton_a1 setState:NSControlStateValueOn];

// TextView
textview = [[[NSTextView alloc] initWithFrame:NSMakeRect(20, 265-100-155, 320, 100)] autorelease];
[textview setFont:[NSFont fontWithName:@"Arial" size:12]];
[textview setDrawsBackground:YES];
[textview setEditable:NO];
[textview setSelectable:NO];