我在嘗試導(dǎo)出Ogre的所有類接口到lua中使用,參考CEGUI的方法,使用的是tolua++來導(dǎo)出C++類對象。在使用過程中,遇到了一些問題。
問題1:
表現(xiàn)為tolua++編譯錯(cuò)誤,錯(cuò)誤信息是:***curr code for error is $pfile "OgreBase/OgreVector2.h"
這里我編寫了一個(gè)OgreBase.pkg文件(給tolua++用來生成導(dǎo)出導(dǎo)入lua的定義文件)
namespace Ogre


{
$pfile "OgreBase/OgreSharedPtr.h"
$pfile "OgreBase/OgreVector2.h"
};

OgreSharedPtr.h文件內(nèi)容如下:
$#include "OgreSharedPtr.h"

/**//// The method to use to free memory on destruction
enum SharedPtrFreeMethod


{

/**//// Use OGRE_DELETE to free the memory
SPFM_DELETE,

/**//// Use OGRE_DELETE_T to free (only MEMCATEGORY_GENERAL supported)
SPFM_DELETE_T,

/**//// Use OGRE_FREE to free (only MEMCATEGORY_GENERAL supported)
SPFM_FREE
};

class SharedPtr


{
TOLUA_TEMPLATE_BIND(T, Ogre::DataStream , Ogre::DataStreamList , Ogre::StringVector , Ogre::FileInfoList)

SharedPtr();
~SharedPtr();
T* get() ;
void bind(T* rep, SharedPtrFreeMethod freeMethod = SPFM_DELETE);
bool unique() ;
unsigned int useCount() ;
T* getPointer() ;
bool isNull(void) ;
void setNull(void);
};OgreVector2.h內(nèi)容如下:
$#include "OgreVector2.h"


class Vector2


{
public:
Real x, y;

public:
inline Vector2();
inline Vector2( Real fX, Real fY );
inline Vector2( Vector2& rkVector );

inline Real operator [] ( size_t i ) ;

inline Real& operator [] ( size_t i );
inline Real* ptr();
inline Real* ptr() ;
inline Vector2& operator = ( Vector2& rkVector );
inline Vector2& operator = ( Real fScalar);

inline bool operator == ( Vector2& rkVector ) ;

inline bool operator != ( Vector2& rkVector ) ;
inline Vector2 operator + ( Vector2& rkVector ) ;

inline Vector2 operator - ( Vector2& rkVector ) ;
inline Vector2 operator * ( Real fScalar ) ;

inline Vector2 operator * ( Vector2& rhs) ;

inline Vector2 operator / ( Real fScalar ) ;

inline Vector2 operator / ( Vector2& rhs) ;

inline Vector2& operator + () ;

inline Vector2 operator - () ;

inline Real length () ;
inline Real squaredLength () ;
inline Real dotProduct( Vector2& vec) ;
inline Real normalise();
inline Vector2 midPoint( Vector2& vec ) ;
inline bool operator < ( Vector2& rhs ) ;
inline bool operator > ( Vector2& rhs ) ;
inline void makeFloor( Vector2& cmp );
inline void makeCeil( Vector2& cmp );
inline Vector2 perpendicular(void) ;
inline Real crossProduct( Vector2& rkVector ) ;
inline Vector2 randomDeviant(
Real angle) ;
inline bool isZeroLength(void) ;
inline Vector2 normalisedCopy(void) ;
inline Vector2 reflect( Vector2& normal) ;
// special points
static const Vector2 ZERO;
static const Vector2 UNIT_X;
static const Vector2 UNIT_Y;
static const Vector2 NEGATIVE_UNIT_X;
static const Vector2 NEGATIVE_UNIT_Y;
static const Vector2 UNIT_SCALE;

};

咋一看,沒任何問題,但是編譯卻錯(cuò)誤。原因在于tolua++對$pfile的處理有些許問題,它是直接把被包含文件粘貼到一個(gè)文件中,而OgreSharedPtr.h最后一行是};,結(jié)果};和$pfile "OgreBase/OgreVector2.h"連在一行中了,結(jié)果出現(xiàn)編譯錯(cuò)誤。解決辦法很簡單,在每行$pfile之后加一行空行,或者在每個(gè)被包含頭文件后保證最后一行是空行即可。
問題2:
tolua++對嵌套類模板的導(dǎo)出bug。編寫如下的pkg文件,為了導(dǎo)出一個(gè)有4個(gè)模板參數(shù)的std::map類到lua中,而4個(gè)模板參數(shù)中有個(gè)模板參數(shù)Ogre::STLAllocator帶有自身的模板參數(shù)嵌套,代碼如下:



namespace Ogre


{
class STLAllocator

{
TOLUA_TEMPLATE_BIND(T, int , short, double, VECTOR3, std::string, IModelViewWrapper*, IDisplaySetting::Property, IDisplaySetting::DisplaySize, IDisplaySetting::AntiAliasingLevel, DataStreamPtr, Plane, PlaneBoundedVolume, Polygon*, std::pair<std::string Ogre::BaseResourceGroupManager::ArchiveIndexEntry>, std::pair<std::string Ogre::BaseResourceGroupManager::BaseResourceGroup*>, Ogre::BaseResourceGroupManager::ResourceLocation*)
};
};
namespace std


{
class less

{
TOLUA_TEMPLATE_BIND(T,std::string)
};
class pair

{
TOLUA_TEMPLATE_BIND(F S,std::string Ogre::BaseResourceGroupManager::ArchiveIndexEntry)
pair();
~pair();
F first;
S second;
};
class map

{
TOLUA_TEMPLATE_BIND(K V S A,std::string Ogre::BaseResourceGroupManager::ArchiveIndexEntry std::less<std::string> Ogre::STLAllocator<std::pair<std::string,Ogre::BaseResourceGroupManager::ArchiveIndexEntry> >)
class iterator

{
pair<K,V> operator->();
};
void clear();
bool empty();
int size() ;
std::map<K,V,S,A>::iterator find( K &key);
std::map<K,V,S,A>::iterator begin();
std::map<K,V,S,A>::iterator end();
std::map<K,V,S,A>::reverse_iterator rbegin();
std::map<K,V,S,A>::reverse_iterator rend();
std::pair<std::map<K,V,S,A>::iterator,bool> insert( std::pair<K,V> &value);
std::map<K,V,S,A>::iterator erase(std::map<K,V,S,A>::iterator iter);
map();
~map();
};

};

用tolua++編譯這個(gè)pkg文件,生成cpp文件時(shí)不會出錯(cuò),但編譯cpp文件時(shí)會出錯(cuò),因?yàn)樗傻腸pp文件中,模板嵌套的代碼有問題,如下:
生成的錯(cuò)誤代碼片段1:
std::map<std::string ,Ogre::BaseResourceGroupManager::ArchiveIndexEntry ,std::less<std::string> ,Ogre::STLAllocator<std::pair<std::string,Ogre::BaseResourceGroupManager::ArchiveIndexEntry> >>

生成的錯(cuò)誤代碼片段2:
std::map<std::string ,Ogre::BaseResourceGroupManager::ArchiveIndexEntry ,std::less<std::string> ,Ogre::STLAllocator<std::pair<std::string,Ogre::BaseResourceGroupManager::ArchiveIndexEntry> >,>這兩段錯(cuò)誤代碼中,第一個(gè)代碼片段最后兩個(gè)尖括號連接在一起了,錯(cuò)誤在于最后兩個(gè)尖括號間沒有空格。
第二個(gè)代碼片段最后兩個(gè)尖括號間多了個(gè)“,”符號。
檢查發(fā)現(xiàn),是tolua++代碼本身有bug,修復(fù)如下:
打開tolua++目錄的lua目錄,打開class.lua文件,181行append = string.gsub(append, ">>", "> >"),這里目的是把兩個(gè)尖括號間加空格,但它沒考慮到把這個(gè)類型與另一個(gè)模板類型嵌套使用的情況,結(jié)果出現(xiàn)代碼片段1的bug,解決辦法是改成append = string.gsub(append, ">>", "> > "),即在最后一個(gè)尖括號后自動加一個(gè)空格,以解決此問題,187行也有同樣的問題,改成bI = string.gsub(bI, ">>", "> > ")即可。
對于錯(cuò)誤的代碼片段2,需要打開declaration.lua,定位到148行,改成local template_part = "<"..concat(m, 1, m.n , ",")..">",這樣就能解決代碼片段2的問題,此問題的起因在于此地方用空格來做模板參數(shù)的分隔符,但模板尖括號間又有空格,結(jié)果把這個(gè)空格自動替換成逗號,導(dǎo)致編譯錯(cuò)誤。
最后,由于Ogre庫比較龐大,暫時(shí)我只完成了Ogre基本庫(數(shù)學(xué)庫、字符串、文件系統(tǒng)等等渲染無關(guān)系統(tǒng))的功能導(dǎo)出到lua,還沒把渲染層導(dǎo)出。
如果本文對你的開發(fā)有所幫助,并且你手頭恰好有零錢。
不如打賞我一杯咖啡,鼓勵(lì)我繼續(xù)分享優(yōu)秀的文章。
