0

RS232ポート用の小さなクラスを書いています。同期書き込みと非同期読み取りが可能です。したがって、非同期読み取りの場合、入力データを待機している2番目のスレッドを使用しています。データを受信したら、入力データを使用してユーザー コールバック (コンストラクターの引数として取得) を呼び出します。次のようになります。

typedef int (*ReceivedCallback)(string data);

class RS232
{
    RS232(string portName, ReceivedCallback dataReceived);
    ~RS232();

private:
    ReceivedCallback dataReceivedCallback;

private:
    static unsigned ReaderThread(void* data);

public:
    SendData(string data);
}

私の問題は次のとおりです。 ReaderThread へのポインターを _beginthreadex() 関数に渡すには、ReaderThread を静的にする必要があります。そして ReaderThread では、コンストラクターでユーザーから取得した「dataReceivedCallback」を呼び出したいと思います。しかし、静的な ReaderThread で非静的関数を呼び出すことができないため、できません。また、「dataReceivedCallback」を静的にすることはできません。これは、自分のクラス (COM1、COM2、COM3 用) のインスタンスが多数ある可能性があり、すべてのインスタンスに、ユーザーが取得した独自のコールバックが必要なためです。

私のアーキテクチャの間違いはどこですか? どのように実装しますか?

前もって感謝します!

PS Visual Studio 2005 を使用しています。

4

3 に答える 3

2

You need to pass a pointer to the instance of RS232 to ReaderThread, which will, in turn, either pass that pointer to a static callback, or directly call non-static methods on the RS232 object.

I would also use [CreateThread][1] rather than beginthreadex. My code samples will use CreateThread, but you can adapt the technique to beginthreadex if you so desire.

Simply, when kicking off the ReaderThread, pass it a pointer to the instance:

RS232* myObj = new RS232;
CreateThread (..., myObj);

...use reinterpret_cast to cast it back:

unsigned RS232::ReaderThread (void* data)
{
  RS232* that = reinterpret_cast <RS232*> (data);
}

Change your callback function so that it can pass the instance as well:

typedef int (*ReceivedCallback)(string data, RS232* that);

And now in the callback you can call member functions:

that->DoSomethingCool (data);
于 2013-07-11T13:26:05.053 に答える
1

静的スレッド関数で非静的オブジェクト データにアクセスするには、この非常にハックでテストされていないソリューションを使用できます。ただし、注意してください --- 非常にハックであるため、教育目的のみです。ロックとミューテックスについて学び、おそらくスレッドを強化する必要があります。これは pthread スタイルのソリューションであることに注意してください。関数 _beginthreadex() の経験はありませんが、 createThread がスレッドを作成する仕事をしていることがわかります。必要に応じて適応します。

typedef int (*ReceivedCallback)(string data);

class RS232
{
public:
    RS232(string portName, ReceivedCallback dataReceived);
    ~RS232();
    SendData(string data);
    createThread();

private:
    ReceivedCallback dataReceivedCallback;
    static unsigned ReaderThread(void* data);
    thread m_someThread;

    struct accessHelper
    {
        RS232* This;
        void *actual_arg;
        accessHelper(RS232 *t, void *p)  
            : This(t), 
              actual_arg(p) 
              {}
    };

};

RS232::createThreaad()
{
     int someData;
     accessHelper ah(this, someData);
     m_someThread.create(RS232::ReaderThread, &ah);
}

RS232::ReaderThread(void *data) 
{
    accessHelper *ah = static_cast<accessHelper*>(data);
    RS232 *This = ah->This;
    This->dataReceivedCallback......
}
于 2013-07-11T13:31:11.220 に答える
1

追加の引数をスレッド関数に渡す必要があります (既にvoid *data利用可能です)。

次に、これをプライベート要素として に追加しますclass RS232

class RS232
{

     RS232(string portName, ReceivedCallback dataReceived);
    ~RS232();

private:
    ReceivedCallback dataReceivedCallback;

private:
    static unsigned ReaderThread(void* data);

public:
    SendData(string data);
}

そしてコンストラクターで:

RS232::RS232(string portName, ReceivedCallback dataReceived)
{
   ... various stuff to initialize the serial port ... 
   _beginthreadex(securityarg, stacksize, ReaderThread, this, ...)
}

そして、ReaderThread 関数では:

unsigned RS232::ReaderThread(void *data)
{
   RS232 *self = static_cast<RS232*>(data);

   .... stuff to read from serial port ... 

   ... Now call the callback:
   self->dataReceivedCallback(str); 
   .... 
}
于 2013-07-11T13:23:43.567 に答える