Squirrel

The programming language
Welcome to Squirrel Sign in | Join | Help
in Search

Feature Request: DECLARE_INSTANCE_TYPE_NAME(classType, desiredName)

Last post 09-19-2006, 9:18 AM by jkleinecke. 5 replies.
Sort Posts: Previous Next
  •  02-23-2006, 1:38 PM 635

    Idea [I] Feature Request: DECLARE_INSTANCE_TYPE_NAME(classType, desiredName)

    I ran into an odd issue with the DECLARE_INSTANCE_TYPE_ macro today; it doesn't seem to handle namespaces very well unless you're using them. For reference:

    //////////////////////////////////////////////////
    Macro
    //////////////////////////////////////////////////
    #define DECLARE_INSTANCE_TYPE_(TYPE) namespace SqPlus { \
      inline const SQChar * GetTypeName(const TYPE & n)            { return _T(#TYPE); } \
      inline void Push(HSQUIRRELVM v,TYPE * value)                 { if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) throw SquirrelError(_T("Push(): could not create INSTANCE (check registration name)")); } \
      inline void Push(HSQUIRRELVM v,TYPE & value)                 { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(_T("Push(): could not create INSTANCE copy (check registration name)")); } \
      inline bool    Match(TypeWrapper,HSQUIRRELVM v,int idx) { return  GetInstance(v,idx) != NULL; } \
      inline bool    Match(TypeWrapper,HSQUIRRELVM v,int idx) { return  GetInstance(v,idx) != NULL; } \
      inline TYPE & Get(TypeWrapper,HSQUIRRELVM v,int idx) { return *GetInstance(v,idx); } \
      inline TYPE * Get(TypeWrapper,HSQUIRRELVM v,int idx) { return  GetInstance(v,idx); } \
      template<> \
      struct TypeInfo { \
        const SQChar * typeName; \
        TypeInfo() : typeName(_T(#TYPE)) {} \
        enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
        operator ScriptVarType() { return ScriptVarType(TypeID); } \
      }; \
    } // nameSpace SqPlus
    //////////////////////////////////////////////////
    End Macro
    //////////////////////////////////////////////////

    For the project I have, I'm using a bunch of different libraries to accomplish various things, and there are a few classes from each that I need to bind to Squirrel. Because of sizes of some of the libraries, I'm not using any namespaces at all to avoid class name conflicts, and that's served me well until right now :-)

    I was binding the class Ogre::Vector3, and called:
    DECLARE_INSTANCE_TYPE(Ogre::Vector3)
    in the headers, and bound it with (pretend I didn't bind any member functions):
    SqPlus::SQClassDef(_T("Vector3"));
    so that a scripter would just have to type 'Vector3 foo;' in their code to make an Ogre::Vector3.

    When I ran this, I ran headfirst into an unhandled exception inside that macro's 'Push' function because it could not construct the class from the classname. This is because the TypeInfo struct and the GetTypeName function that the macro creates takes the full class as a string, in this case 'Ogre::Vector3'. The bind command does not have a matching string; it only has 'Vector3'.

    Calling 'using namespace Ogre' before the macro call would fix the problem, but it would break a signifigant portion of my code as I have Ogre:: everywhere. Calling 'typedef Ogre::Vector3 Vector3' before the macro call would also work, but doesn't scale well and starts to resemble the first solution if enough classes are bound.

    So I was wondering if anyone would be willing to change the relevant section of sqplus.h to look like the one below. This change should not be interface breaking, and adds support for cases like mine. SqPlusConst.h may also need to be changed, but it doesn't look like there are any name references in there.

    //////////////////////////////////////////////////
    Altered SqPlus.h
    //////////////////////////////////////////////////
    #define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
        inline const SQChar * GetTypeName(const TYPE & n)            { return _T(#NAME); } \
        inline void Push(HSQUIRRELVM v,TYPE * value)                 { if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) throw SquirrelError(_T("Push(): could not create INSTANCE (check registration name)")); } \
        inline void Push(HSQUIRRELVM v,TYPE & value)                 { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(_T("Push(): could not create INSTANCE copy (check registration name)")); } \
        inline bool    Match(TypeWrapper,HSQUIRRELVM v,int idx) { return  GetInstance(v,idx) != NULL; } \
        inline bool    Match(TypeWrapper,HSQUIRRELVM v,int idx) { return  GetInstance(v,idx) != NULL; } \
        inline TYPE & Get(TypeWrapper,HSQUIRRELVM v,int idx) { return *GetInstance(v,idx); } \
        inline TYPE * Get(TypeWrapper,HSQUIRRELVM v,int idx) { return  GetInstance(v,idx); } \
        template<> \
    struct TypeInfo { \
        const SQChar * typeName; \
        TypeInfo() : typeName(_T(#NAME)) {} \
        enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
        operator ScriptVarType() { return ScriptVarType(TypeID); } \
    }; \
    } // nameSpace SqPlus

    #ifndef SQPLUS_CONST_OPT
    #define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_(TYPE,TYPE)
    #define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME)
    #else
    #define SQPLUS_DECLARE_INSTANCE_TYPE_CONST
    #include "SqPlusConst.h"
    #endif
    //////////////////////////////////////////////////
    End Altered SqPlus.h
    //////////////////////////////////////////////////

    If not, I hope that helps someone :-)

    --Ben
  •  02-26-2006, 4:25 PM 645 in reply to 635

    Re: Feature Request: DECLARE_INSTANCE_TYPE_NAME(classType, desiredName)

    I have tested this change and it works OK (also updated SqPlusConst.h). I'll add it to the next release (if anyone needs it sooner, let me know and I'll post just this change in the Wiki).

    DECLARE_INSTANCE_TYPE_NAME changes have been uploaded to the Wiki: http://wiki.squirrel-lang.org/default.aspx/SquirrelWiki/SqPlus.html

  •  09-15-2006, 10:56 AM 1176 in reply to 645

    Re: Feature Request: DECLARE_INSTANCE_TYPE_NAME(classType, desiredName)

    I'm a bit confused.  What precisely does this DECLARE_INSTANCE_TYPE macro do (I can see it adding things to SQPlus's namespace, but can't infer what use I'd make of them)?

    I have been successfully using SQPLus with simple bindings such as that shown below, and nothing (at all) in my C++ header files.

    // static
    void
    App::bindToSquirrel()
    {
       SQClassDef&lt;App&gt;(_T("App"))     
          .var(&App::mAppName,_T("appName"))
          .var(&App::mWindowTitle,_T("windowTitle"))     
          .var(&App::mOgreFilename,_T("ogreFilename"))
          .var(&App::mLogFilename,_T("logFilename"))     
          .func(&App::configure,_T("configure"))
          .func(&App::initOgre,_T("initOgre"))
          .func(&App::go,_T("go"))
          ;
    }

    What am I missing in my present use of SQPlus?

    edit:  I think I have a guess.  Without this, I cannot call BindVariable() on instances of c++ objects to make them (say) globals in Squirrel-space?  I had not done that yet.

    tone

  •  09-16-2006, 7:28 AM 1177 in reply to 1176

    Re: Feature Request: DECLARE_INSTANCE_TYPE_NAME(classType, desiredName)

    This macro, and DECLARE_INSTANCE_TYPE, allows you to pass c++ variables into and out of SqPlus as locals. The only difference between the two macros is one allows you to manually pick the name, while the other uses the class name. My first post goes into the details of why you'd need to pick your own sometimes.

    What you're doing is the part that allows Squirrel to call c++ object member functions / member variables in Squirrel. To avoid any nasty errors later, you should be doing both :-) Just make sure that the names match. If you do something like:
    DECLARE_INSTANCE_TYPE_NAME(Ogre::Vector3,"Vector3")

    Be sure that the member function line looks like:
    SQClassDef<Ogre::Vector3>(_T("Vector3"))

    --Ben
  •  09-16-2006, 10:16 AM 1178 in reply to 1177

    Re: Feature Request: DECLARE_INSTANCE_TYPE_NAME(classType, desiredName)

    You're a peach. I have now got all the above working, I think.

    Suggestion: it would be nice to have all these macros have a SQ_ prefix on them, to better assist reading of code that draws upon many such underlying elements as Ogre3D, TNL, Squirrel, SQPlus, etc. It helps one understand what kind of things are being accomplished, e.g.: "oh, that must be part of the scripting layer"

    tone
  •  09-19-2006, 9:18 AM 1185 in reply to 1178

    Re: Feature Request: DECLARE_INSTANCE_TYPE_NAME(classType, desiredName)

    Yeah, I ran into the exact same problem you are having.  John Schultz said that he would put some documentation around the macros for the next release, but in the mean time I did add a section to the wiki that outlines what I found:
    http://wiki.squirrel-lang.org/default.aspx/SquirrelWiki/SqPlusFAQ.html
View as RSS news feed in XML
Powered by Community Server, by Telligent Systems