[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 メーリングリストの案内