C
CはC++の祖先であり、低レベルシステムにおける共通言語(リングワフランカ)であり続けている。オペレーティングシステムのカーネル、デバイスドライバ、センサーファームウェア、多くの組み込みランタイムはCで書かれている。SLAMシステム全体をCで書くことはまずないが、Cのコードを読んだり、それとインターフェースを取ったりすることは常に発生する。
学ぶべきこと
- ポインタとメモリ:
malloc/free、ポインタ演算、配列とポインタの違い。CにはスマートポインタやRAIIが存在せず、すべてのメモリ確保はプログラマの責任である。これを理解することで、C++の抽象化(とそのコスト)がより明確に見えるようになる。 - 構造体と関数: Cのプログラムはクラスではなく、単純なデータ構造とフリー関数を中心に構成される。多くの高性能ライブラリは、予測可能なメモリレイアウトを得るためにこのスタイルを保持している。
- 関数ポインタ: コールバックのためのCの仕組み。センサーSDKは、登録した関数ポインタを呼び出すことでフレームを配信する。以下のパターンは、ほぼすべてのカメラ/IMUドライバAPIに見られる形である。
- コンパイルモデル: ヘッダー、翻訳単位、リンク、
extern "C"。これはC++が継承しているモデルと同じであり、SLAMプロジェクトで遭遇するビルドエラー(未定義参照、ABIの不整合)の多くは、このモデルを理解すれば格段にデバッグしやすくなる。
#include <stdlib.h>
typedef struct { float x, y, z; } Point3;
Point3* cloud_alloc(size_t n) {
return (Point3*)malloc(n * sizeof(Point3)); /* must free() later */
}
/* Callback registration, the universal sensor-SDK pattern */
typedef void (*frame_cb)(const unsigned char* data, int w, int h, void* user);
void sensor_set_callback(frame_cb cb, void* user_data);
CとC++のブリッジ
C++コンパイラは型情報を符号化するために関数名をマングルするが、Cはそうしない。extern "C"は、C++コンパイラにC言語のリンケージを使うよう指示することで、両者が互いを呼び出せるようにする。
extern "C" {
#include "vendor_camera_sdk.h" // C header from the sensor vendor
}
// C++ wrapper: RAII around the C API's open/close pair
class Camera {
public:
Camera() { handle_ = vendor_cam_open(); }
~Camera() { vendor_cam_close(handle_); }
private:
vendor_cam_handle* handle_;
};
このラッパーパターン——内側にCのAPI、外側にRAII——は、うまく設計されたSLAMコードベースがCインターフェースの危険性を封じ込める方法である。
SLAM作業においてCが現れる場所
- センサードライバとSDK: カメラ、IMU、LiDARのベンダーはしばしばC APIを提供し、あなたのC++ラッパーは
extern "C"インターフェース経由でそれらを呼び出す。 - 組み込み・マイコンコード: 計算リソースが限られたプラットフォーム(ドローン、組み込みボード)では、センサー側のコードは純粋なCであることが多い。
- バインディング: Pythonの拡張モジュールや多くのクロス言語インターフェースは、CのABIレベルで定義される。CのABIが安定した共通基盤だからである。
よくある落とし穴
- メモリリークと二重解放:
mallocには正確に1回のfreeが必要であり、30 Hzのフレームコールバック内のリークは数分でメモリを使い果たす。 - ダングリングポインタ: センサーのコールバックはしばしばバッファを一時的に借用させるだけで、コールバックが戻った後は無効になる。必要なデータはコピーし、ポインタ自体を保持してはならない。
- 所有権が文書化されていない: C++のスマートポインタとは異なり、C APIのヘッダーは誰が何を解放すべきかをほとんど記述しない。ハンドルを返す関数についてはドキュメント(またはソースコード)を確認すること。
- 構造体レイアウトの思い込み: バイトバッファを構造体にキャストすると、パディングやアライメントの違いによって壊れる。ワイヤーやABIを跨ぐデータには明示的な(デ)シリアライゼーションを使うこと。
SLAMにおける意義
リアルタイムSLAMはハードウェアの近くで動作し、あなたのアルゴリズムとセンサー、OS、アクセラレータとの境界はほぼ常にCインターフェースである。Cを流暢に読める——そして手動メモリ管理を理解している——ことは、あなたをより良いC++プログラマにし、ドライバのコールバックからバンドル調整に至るまで全スタックをデバッグできるようにする。多くの学習者にとって、Cは独立した深い学習対象というより、C++学習の伴走者として扱えばよい。