[openrtm-users 00031] Re: Windowsへの移植
稲村 渡
wataru_inamura @ ihi.co.jp
2005年 10月 18日 (火) 16:16:09 JST
稲村@IHIです。
ずいぶん時間が経ってしまいましたが、報告します。
VC6で使えるようになりました。
[1] 全般
using namespace std;を削除し、std名前空間を明示する。
これをやらないと、いろいろとコンパイルエラーがでる。
以下のファイルを修正。
RtcBase.h,RtcBase.cpp,
RtcConfig.h,
RtcManager.h,RtcManager.cpp,
RtcModuleProfile.h,RtcModuleProfile.cpp,
RtcNaming.h,RtcNaming.cpp,
RtcOutPort.h,
RtcOutPortBase.h,RtcOutPortBase.cpp,
[2] RtcBase.h
1. USLEEPマクロをVC6で動作するように修正。
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
# define USLEEP(x) Sleep(x/1000);
#else
# define USLEEP(x) usleep(x);
#endif
2. ComponentStateをenumで定義。
VC6ではconstで定義した定数を定数式と判断してくれないためcaseラベルに使えない。 そのため、以下のようにenumで定義しなおした。
数値が一致することを常に確認しなければならない。これは、苦肉の策。もっと良いやり方はないか?
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
enum ComponentStateVC6{
RTC_UNKNOWN = 0,
RTC_BORN = 1,
RTC_INITIALIZING= 2,
RTC_READY = 3,
RTC_STARTING = 4,
RTC_ACTIVE = 5,
RTC_STOPPING = 6,
RTC_ABORTING = 7,
RTC_ERROR = 8,
RTC_FATAL_ERROR = 9,
RTC_EXITING = 10,
};
#else
const ComponentState RTC_UNKNOWN = RTM::RTComponent::RTC_UNKNOWN;
const ComponentState RTC_BORN = RTM::RTComponent::RTC_BORN;
const ComponentState RTC_INITIALIZING = RTM::RTComponent::RTC_INITIALIZING;
const ComponentState RTC_READY = RTM::RTComponent::RTC_READY;
const ComponentState RTC_STARTING = RTM::RTComponent::RTC_STARTING;
const ComponentState RTC_ACTIVE = RTM::RTComponent::RTC_ACTIVE;
const ComponentState RTC_STOPPING = RTM::RTComponent::RTC_STOPPING;
const ComponentState RTC_ABORTING = RTM::RTComponent::RTC_ABORTING;
const ComponentState RTC_ERROR = RTM::RTComponent::RTC_ERROR;
const ComponentState RTC_FATAL_ERROR = RTM::RTComponent::RTC_FATAL_ERROR;
const ComponentState RTC_EXITING = RTM::RTComponent::RTC_EXITING;
#endif
3. friend class ThreadStates; 追加
class ThreadStatesのコンストラクタで使用しているRUNNINGは、
RtcBaseクラスのprotectedのため、エラーとなる。
TreadStatesをRtcBaseのfriendとした。
[3] RtcBase.cpp
1. sleep -> USLEEP
[5] RtcInPort.h
1. m_Bufferの宣言位置変更→gccのWARNING(宣言の順番と初期化並びの順番が前後している)への対処
[6] RtcManager.h
1. class LogEmitterのoperator()が戻り値を返していない。
適当な値(0)を返すように修正。
しかし、この演算子にそもそも戻り値は必要なのか疑問。
class LogEmitter
: public RtcSyncCallback
{
public:
LogEmitter(OutPortAny<TimedString>& port, TimedString& var)
: m_OutPort(port), m_Var(var)
{
}
virtual int operator()(const char* s)
{
m_Var.data = CORBA::string_dup(s);
m_OutPort.write();
return 0; // 追加
}
[7] RtcManager.cpp
1. usleep -> USLEEP
2. CPU負荷100%となる問題に対処
以下のように、2箇所のwhile内に、スリープを入れることで、ビジーループではなくなる。
暫定処置。本当にこれでよいかは要検討。
void RtcManager::runManager()
{
// start POA manager
m_pPOAManager->activate();
if (CORBA::is_nil(m_pORB))
{
RTC_ERROR(("Invalid ORB pointer."));
exit(1);
}
// m_pORB->run();
while (g_mgrActive)
{
USLEEP(1000); // ビジーループ回避のためにスリープを入れる */
if (m_pORB->work_pending()){
m_pORB->perform_work();
}
}
shutdown();
while (m_pORB->work_pending())
{
USLEEP(1000); // ビジーループ回避のためにスリープを入れる */
if (m_pORB->work_pending())
m_pORB->perform_work();
}
[8] RtcModuleProfile.h
1. typedef 名を明示 → VC6の警告に対処
typedef struct RtcModuleProfSpec {
RtcModuleProfileType type;
char* value;
} RtcModuleProfSpec;
[9] RtcModuleProfile.cpp
1. メソッドappendInPortProfile(),appendOutPortProfile()が戻り値を返していない。
適当な値(true)を返すように修正。
[10] RtcNameComponent.cpp
1. メソッドpush()
VC6の問題で、for(int i;...) ... for(int i; )とすると、
intを同じスコープで再定義したことになる。int i; の定義をforの外に置く。
[11] RtcNaming.cpp
1. メソッドpickupNode() が戻り値を返していない。
適当な値(true)を返すように修正。
[12] RtcOutPort.h
1.VC6では、clock_gettimeがなく、ACE_OS::clock_gettimeの実装も何も処理をしていない。
マクロ ACE_HAS_CLOCK_GETTIMEの定義部を以下のように修正。
#if defined(_MSC_VER) && (_MSC_VER <= 1200) // VC6以前
#else
#define ACE_HAS_CLOCK_GETTIME // VC6ではclock_gettimeは存在しない。
#endif
メソッドwrite()を以下のように修正。
#if defined (_MSC_VER) && (_MSC_VER <= 1200) // VC6以前
ts = ACE_OS::gettimeofday();
#else
ACE_OS::clock_gettime(CLOCK_REALTIME, &ts);
#endif
[13] RtcRingBuffer.h
1. メソッドget_backがvirtualになっているのを、inlineに修正。
2.m_Oldestの宣言位置を最後に移動。→gccのWARNING(宣言の順番と初期化並びの順番が前後している)への対処
[14] RtcSubscriber.h
1. メソッドupdate(), svc() のデフォルト実装が戻り値を返していない。
適当な値(trueと0)を返すように修正。
[15] RtcSubscriber.cpp
1. メソッド int SubscriberPeriodic::svc(void)が戻り値を返していない。
適当な値(0)を返すように修正。
2. sleep(1); -> ACE_OS::sleep( ACE_Time_Value(1,0) );
[16] RtcSystemLogger.h
1. VC6に存在しない定義を追加。
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
# define LINE_MAX 2048
# define vsnprintf _vsnprintf
# define __restrict
#endif
2. std::char_type, std::traits_type
コンパイルエラー「char_type, traits_typeは'std' のメンバではありません。」
が発生するため、以下のように修正。
typedef _CharT char_type;
typedef _Traits traits_type;
3. std::string::basic_string -> std::basic_string
VC6には、std::string::basic_stringがないので以下のように修正。
virtual int sync()
{
std::basic_string<_CharT> s(this->pbase(),
this->pptr() - this->pbase());
4. ERRORマクロとの衝突。
VC6では、WINGDI.HにマクロERRORが定義されている。
#define ERROR 0
以下のように、ERRORを使っているところを、ERROR_に修正。
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
enum {SILENT, ERROR_, WARN, INFO, NORMAL, DEBUG, TRACE, VERBOSE, PARANOID, MANDATORY };
#else
enum {SILENT, ERROR, WARN, INFO, NORMAL, DEBUG, TRACE, VERBOSE, PARANOID, MANDATORY };
#endif
5. 自動変数の配列定義に定数が使われていない。
メソッドgetFmtDate の以下の記述は、コンパイルエラー「定数式が必要です」が発生する。
int maxsize(256);
char buf[maxsize];
次のように修正。これは、VC6が正しいはず。
const int maxsize(256);
char buf[maxsize];
####################################################
ちょっとした機能拡張
[1] 構成ファイル(rtc.conf)の内容を、コンポーネントクラスで利用できるようにする。
たとえば、
rtc.confにシリアルポートの指定を以下のように追加しておいて、
SeralPort /dev/ttyS0
デバイスとシリアルポートで通信するコンポーネントのrtc_init_entryで、
std::stirng port = getCofigValue("SerialPort");
m_dev.Open( port );
などと使えるようにしたい。
1. RtcConfigクラス
(1) コンフィグレーション情報を取得できるように修正。
以下の関数を追加。
/*!
* @if jp
* @brief コンフィグレーション情報取得
* 任意のキーを指定してコンフィグレーション情報を取得する。
* @param a_configKey キー文字列
* @return 値文字列。見つからなかった場合は、空文字列となる。
* @else
* @endif
*/
std::string getConfigValue(
const std::string& a_configKey
) const
{
std::map<std::string, std::string>::const_iterator ci
= m_Config.find(a_configKey);
if( ci != m_Config.end() )
{
return ci->second;
}
else
{
return "";
}
}
2. RtcBaseクラス
/*!
* @brief 構成情報取得
* 任意のキーを指定して構成情報を取得する。
* @param a_configKey キー文字列
* @return 値文字列。見つからなかった場合は、空文字列となる。
*/
std::string getConfigValue(
const std::string& a_configKey
) const
{
return m_pManager->getConfig().getConfigValue(a_configKey);
}
openrtm-users メーリングリストの案内