特定のハードウェアとのすべての通信を処理するクラスがあります。ハードウェアは、1 つのソケットを介してデータを更新する必要があり、既知の (そしてハードコードされた) マルチキャスト アドレスでハンドシェイクの目的でその IP をブロードキャストします。
その結果、クラスは 2 つのスレッドを生成します。1 つのスレッドは、ハードウェアとの直接通信を処理し、クラスのメンバー構造に基づいてデータを更新します。もう一方のスレッドは、マルチキャスト アドレスを継続的に監視して、IP が変更されたかどうかを確認します。
両方のスレッドは、クラス内の静的メンバー関数として実装されます。ただし、pthreads を使用するには、extern "C" として宣言する必要があると理解しています。とはいえ、私の調査によると、クラスのメンバー関数を extern "C" として宣言することはできません。以前このプロジェクトに携わったエンジニアがこの問題を回避するコードを見たのは、スレッド化された関数の実装が extern "C" で囲まれていることです。つまり、extern "C" は関数の宣言または定義に含まれていませんが、関数定義全体が extern "C" {} にカプセル化されています。
このような:
extern "C" {
// function goes here
}
コードの理解を深め、マルチスレッド プログラミングのスキルを向上させたいと考えているため、この実装についていくつか質問があります。
extern "C" は、実装されている方法で実際に何かを行いますか? ここで修飾子が実際に行うことについて読みました: In C++ source, what is the effect of extern "C"? しかし、この場合、クラスの静的メンバーである関数を扱っているという事実を考えると、実際に適用できますか?
スレッド化されたメンバー関数は、 reinterpret_cast を実行してクラスへのポインターを作成することにより、クラスのメンバー変数を変更するという事実を回避しているようです。そのキャストを見たときに危険信号が発生したため、これは標準的な慣行ですか?
コンストラクターは pthread_create() を呼び出してスレッドを起動します。ある時点で 1 つのインスタンスのみがハードウェアと通信できるようにする静的メンバー変数を追加するようなことを計画していました。つまり、呼び出し元がクラスの複数のインスタンスを持つことを許可することを考えていましたが、一度に「接続」できるのは 1 つだけです。これは標準的な慣行ですか、それとも私の考え方に「ハッキー」なものがありますか? 特定の時点で接続されるハードウェアは 1 つだけであるため、特定の時点で動作するクラス インスタンスが 1 つだけである必要があります。
ご助力いただきありがとうございます。また、「おい、Boost スレッドを使用してください、FTW」のようなことを提案する場合は、息を止めてください。最終的にはスレッド ライブラリに移行しますが、Boost は POSIX システムで pthread をラップするだけであると理解しています。その結果、ライブラリで自分を台無しにする前に、まず生のスレッドの使用について学びたいと思っています。私の主な目標は時間通りに成果を出すことですが、途中で何も学べないとは誰も言いませんでした。;)
追加するために編集:
明確にするために、私が見ている問題を説明するソースコードを次に示します。この場合、extern「C」が何かをしているとはまだ100%確信が持てません...
私の.hで:
class MyClass
{
private:
static void* ThreadFunc(void* args); // extern "C" not found in declaration
static bool instance_;
};
私の.cppで:
MyClass::MyClass() {
if (!instance_) {
instance_ = true;
// spawn threads here
} else {
// don't spawn threads and warn user
}
}
extern "C" {
void *MyClass::ThreadFunc(void* args) { //definintion wrapped in extern C
MyClass* myclass_ptr = static_cast<MyClass*>(args);
// ... more code
return static_cast<void*> 0;
}