我在尝试导出Ogre的所有类接口到lua中使用,参考CEGUI的方法,使用的是tolua++来导出C++类对象。在使用过程中,遇到了一些问题。 问题1: 表现为tolua++编译错误,错误信息是:***curr code for error is $pfile "OgreBase/OgreVector2.h" 这里我编写了一个OgreBase.pkg文件(给tolua++用来生成导出导入lua的定义文件)
namespace Ogre { $pfile "OgreBase/OgreSharedPtr.h" $pfile "OgreBase/OgreVector2.h" };
OgreSharedPtr.h文件内容如下:
$#include "OgreSharedPtr.h" /**//// The method to use to free memory on destructionenum 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内容如下:
$#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;
};
咋一看,没任何问题,但是编译却错误。原因在于tolua++对$pfile的处理有些许问题,它是直接把被包含文件粘贴到一个文件中,而OgreSharedPtr.h最后一行是};,结果};和$pfile "OgreBase/OgreVector2.h"连在一行中了,结果出现编译错误。解决办法很简单,在每行$pfile之后加一行空行,或者在每个被包含头文件后保证最后一行是空行即可。 问题2: tolua++对嵌套类模板的导出bug。编写如下的pkg文件,为了导出一个有4个模板参数的std::map类到lua中,而4个模板参数中有个模板参数Ogre::STLAllocator带有自身的模板参数嵌套,代码如下:
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++编译这个pkg文件,生成cpp文件时不会出错,但编译cpp文件时会出错,因为它生成的cpp文件中,模板嵌套的代码有问题,如下:
生成的错误代码片段1: std::map<std::string ,Ogre::BaseResourceGroupManager::ArchiveIndexEntry ,std::less<std::string> ,Ogre::STLAllocator<std::pair<std::string,Ogre::BaseResourceGroupManager::ArchiveIndexEntry> >>
生成的错误代码片段2: std::map<std::string ,Ogre::BaseResourceGroupManager::ArchiveIndexEntry ,std::less<std::string> ,Ogre::STLAllocator<std::pair<std::string,Ogre::BaseResourceGroupManager::ArchiveIndexEntry> >,> 这两段错误代码中,第一个代码片段最后两个尖括号连接在一起了,错误在于最后两个尖括号间没有空格。 第二个代码片段最后两个尖括号间多了个“,”符号。 检查发现,是tolua++代码本身有bug,修复如下: 打开tolua++目录的lua目录,打开class.lua文件,181行append = string.gsub(append, ">>", "> >"),这里目的是把两个尖括号间加空格,但它没考虑到把这个类型与另一个模板类型嵌套使用的情况,结果出现代码片段1的bug,解决办法是改成append = string.gsub(append, ">>", "> > "),即在最后一个尖括号后自动加一个空格,以解决此问题,187行也有同样的问题,改成bI = string.gsub(bI, ">>", "> > ")即可。 对于错误的代码片段2,需要打开declaration.lua,定位到148行,改成local template_part = "<"..concat(m, 1, m.n , ",")..">",这样就能解决代码片段2的问题,此问题的起因在于此地方用空格来做模板参数的分隔符,但模板尖括号间又有空格,结果把这个空格自动替换成逗号,导致编译错误。 最后,由于Ogre库比较庞大,暂时我只完成了Ogre基本库(数学库、字符串、文件系统等等渲染无关系统)的功能导出到lua,还没把渲染层导出。 如果本文对你的开发有所帮助,并且你手头恰好有零钱。
不如打赏我一杯咖啡,鼓励我继续分享优秀的文章。
|