tolua++导出C++类的一些问题和解决方法

我在尝试导出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 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内容如下:
$#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 , shortdouble, 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,还没把渲染层导出。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
tolua++是一个将C/C++代码导出Lua的工具,它可以将C/C++代码转换成Lua解释器调用的API,并在运行时将C/C++代码封装成Lua可用的函数。 以下是一个简单的示例,演示如何使用tolua++C++代码转换成Lua可调用的库: ```c++ // example.h class Example { public: Example(int value); int getValue(); private: int m_value; }; ``` ```c++ // example.cpp #include "example.h" Example::Example(int value) : m_value(value) { } int Example::getValue() { return m_value; } ``` 首先,我们需要使用tolua++生成绑定代码。假设我们的绑定代码文件名为examplebindings.pkg,其内容如下: ``` // examplebindings.pkg $#include "example.h" module example { class Example { public: Example(int value); int getValue(); }; } ``` 然后,我们可以使用tolua++命令行工具将绑定代码生成为C++头文件和Lua文件: ``` $ tolua++ -o examplebindings.h -H examplebindings.hpp examplebindings.pkg ``` 生成的examplebindings.h和examplebindings.hpp文件包含了C++的绑定代码,我们需要将其与原始的C++代码一起编译成库文件。 接下来,我们可以编写Lua脚本来调用C++代码: ```lua -- example.lua require "examplebindings" local example = example.Example(42) print(example:getValue()) -- 输出42 ``` 在上面的示例中,我们首先加载了examplebindings模块,然后创建了一个Example对象,并调用了其getValue()方法。注意,我们使用了冒号语法来调用方法,这是Lua中常用的一种语法。 最后,我们可以使用Lua解释器来运行example.lua脚本,以调用C++代码并输出结果。 以上就是使用tolua++C++代码转换成Lua可调用的库的基本流程。需要注意的是,tolua++只支持部分C++特性,例如模板和多重继承等特性可能无法正确导出。在实际使用中,我们需要根据具体情况进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值