Zigを使ってSourceModのextensionを記述したかった
モチベーション:
現行のSourceエンジンのプラグイン開発はSourceModのプラグイン開発が主流
ただし、SourcePawn自体がかなり古い言語なので、C++を書くときのような苦痛が結構ある
ネイティブプラグインの開発や、MetaMod:Sourceからの開発はC++で記述する必要があり、負担が大きい
SourceModのextensionであれば、SourcePawnからの利用も可能かつ、SourceModからのEvent/Forwardを上手く活用しつつ、SourcePawnより低レイヤーの処理が記述出来る
C++のインターフェースに従っていれば開発は可能そうではあるので、自身のC++経験がかなり浅いことと、なんとなくZigが気になっていたので、実用性と開発効率をいったん無視して開発してみる。
まずはAlliedModdersのwikiのWriting Extensions を参考に、SourceMod SDKとhl2sdkをインストールする。
今回はcsgoを使用するため、csgoブランチから引っ張ってくる。
Zigの経験が浅いので、GitHub Copilotに助けを求める。
deferがブロック外で記載されていたり、client変数がint型だったのでi32に修正したりなどして出来たコードが以下。
const std = @import("std");
const c = @cImport({
@cInclude("smsdk_ext.h");
});
// イベントハンドラ
pub fn onChatHandler(client: i32, text: []const u8) void {
std.debug.print("Chat message received from client {}: {}\n", .{ client, text });
}
// Forwardの定義
const OnChat = c.defineForward("OnChat", .{});
// イベントの登録
pub fn registerEvents() void {
defer c.finalizeForward(OnChat);
c.registerEvent(OnChat, .{&onChatHandler});
}
以下コマンドで、取り急ぎコンパイルが通ることを確認。
動作確認は実施していない。
zig build-lib -dynamic -target x86_64-linux-gnu ext.zig
どうやらC++の場合、動作の実装、フォワードの作成、ロード時の読み込みとアンロード時の開放が必要になりそう。
いったん基礎を学びたいので、C++で書かれたsample_extの実装を学んでみる。
軽く読んだけど、これワンチャンMetaModSourceのExtensionから学んだ方が良いか?
コンパイルしたライブラリを csgo-dedicated/csgo/addons/sourcemod/extensions
に放り込む。
名前は拡張子は .ext.so である必要があり、ロード時は拡張子を省略する必要がある。
したがって、成果物のファイル名を libext.ext.so
にして、以下コマンドでロードしてみる。
sm exts load libext
[SM] Extension libext.ext.so failed to load: Unable to find extension entry point
エントリーポイントが見つからないと怒られた。
GetSMExtAPI
のシンボルアドレスが見つからない際に発生するエラーのようだ。
smsdk_ext.h
に含まれていたが、さらにsourcepawnのincludeにも依存しているため、正しくインクルードしてtranslateするMakefileを作成した。
build:
zig build-lib -dynamic -target x86-linux-gnu src/ext.zig -lc -lsmsdk_ext
translate:
zig translate-c -lc \
-I/mnt/c/Users/Flowing/Documents/GitHub/sourcemod-sample-ext-zig/sdk/sourcemod/public \
-I/mnt/c/Users/Flowing/Documents/GitHub/sourcemod-sample-ext-zig \
-I/mnt/c/Users/Flowing/Documents/GitHub/sourcemod-sample-ext-zig/sdk/sourcepawn/include \
/mnt/c/Users/Flowing/Documents/GitHub/sourcemod-sample-ext-zig/sdk/sourcemod/public/smsdk_ext.h > src/smsdk_ext.zig
ここで問題発生。
そもそも根本の勘違いとして、ZigはC++ではなくCとの互換をサポートしている。
そして、そもそもSourceMod SDKはC++だった。なぜ気付かなかった...
いったん諦めて、別スクラップにてRustを使って同じことが出来ないか試してみようと思う。