Nasal/CppBind: Difference between revisions

Jump to navigation Jump to search
m
Line 52: Line 52:


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
// NasalDemo.hxx
#include <Main/globals.hxx>
#ifndef SCRIPTING_NASAL_DEMO_HXX
#include <Main/util.hxx>
#define SCRIPTING_NASAL_DEMO_HXX
 
#include <simgear/nasal/nasal.h>
naRef initNasalDemo(naRef globals, naContext c);


#endif // of SCRIPTING_NASAL_DEMO_HXX
// $FG_SRC/Scripting/NasalTest.cxx
</syntaxhighlight>
That's it. Next, create the NasalDemo.cxx source file:
<syntaxhighlight lang="cpp">
// $FG_SRC/Scripting/NasalDemo.cxx
   
   
#include <simgear/nasal/cppbind/from_nasal.hxx>
#include <simgear/nasal/cppbind/from_nasal.hxx>
Line 73: Line 64:
//the struct we want to expose to Nasal (could also be a class obviously)
//the struct we want to expose to Nasal (could also be a class obviously)
struct Test {
struct Test {
  int x,y,z;
  int value;
  void hello() {
  void hello() {
   std::cout << "Hello World from CppBind!\n";  
   std::cout << "Hello World from CppBind!\nValue is:" << value ;  
  }
  }
void setValue(const int val) {value=val;}
int getValue() const {return value;}
};
};
   
   
// cppbind manages all objects as shared pointers, use boost::shared_ptr or SGReferenced objects
// cppbind manages all objects as shared pointers
// use boost::shared_ptr or SGReferenced objects
// typically, you'll want to provide two helper
// functions for each of your classes
 
typedef boost::shared_ptr<Test> Test_ptr;
typedef boost::shared_ptr<Test> Test_ptr;
typedef nasal::Ghost< Test_ptr > NasalTest;
typedef nasal::Ghost< Test_ptr > NasalTest;
   
   
// next, two helper functions that tell cppbind how to
// next, two helper functions that tell cppbind how to
// convert our objects between C++  <-> Nasal
// convert our objects when passing them between C++  <-> Nasal
 
naRef to_nasal_helper(naContext c, Test *src)
// this will be used whenever you want to turn a C++ object into a Nasal Ghost
naRef to_nasal_helper(naContext c, Test *obj)
   {  
   {  
     Test_ptr ptr(src); // set up a smart pointer wrapping src
     Test_ptr ptr(obj); // set up a smart pointer wrapping obj
     return NasalTest::create(c, ptr ); // return the smart pointer wrapped in a naGhost
     return NasalTest::create(c, ptr ); // return the smart pointer wrapped in a naGhost
   }
   }
   
   
// and this will be used whenever you want to turn a Nasal Ghost
// into a C++ object
Test*
Test*
from_nasal_helper(naContext c, naRef ref, const Test*)
from_nasal_helper(naContext c, naRef ref, const Test*)
Line 99: Line 100:
   
   
   
   
// create a new Test object and returns it to Nasal
// add this to FGNasalSys::init():
// as a naRef, wrapped in an naGhost
/*
//  
extern initNasalDemo(naRef globals, naContext c); // or add it to the header
 
if( !NasalDemo::isInit() )
initNasalDemo(_globals, _context);
*/
static naRef f_newtest(const nasal::CallContext& ctx)
static naRef f_newtest(const nasal::CallContext& ctx)
{
{
   Test* t = new Test();
   Test* t = new Test();
   // do some initial state setup
   // we can do some initial state setup now
   t->x = 100;
   t->value=100;
  t->y = 200;
  t->z = 300;
   // and now return the new object to Nasal  
   // and now return the new object to Nasal  
   return ctx.to_nasal( t );
   return ctx.to_nasal( t ); // NOTE: this only calls to_nasal - the to_nasal_helper we provided above is internally used
}
}
   
   
Line 122: Line 115:
// this will register our bindings in the Nasal engine
// this will register our bindings in the Nasal engine
// it should  be called at the end of $FG_SRC/Scripting/NasalSys.cxx::FGNasalSys::init()
// it should  be called at the end of $FG_SRC/Scripting/NasalSys.cxx::FGNasalSys::init()
//
// to call the code, add this to FGNasalSys::init():
/*
if( !NasalDemo::isInit() )
initNasalDemo(_globals, _context);
*/
naRef initNasalDemo(naRef globals, naContext c)
naRef initNasalDemo(naRef globals, naContext c)
{
{
     // This only needs to be called once for each ghost
     // This only needs to be called once for each ghost, so make sure to use the ::isInit() check in FGNasalSys::init()
     NasalTest::init("Test") // this is the ghost's symbol used in error messages/diagnostics (it is NOT the namespace/symbol used by nasal code!)
     NasalTest::init("Test") // this is the ghost's symbol used in error messages/diagnostics (it is NOT the namespace/symbol used by nasal code!)
                 .method("hello", &Test::hello); // add a method to the ghost and map it to the method in the struct/class
                 .method("hello", &Test::hello) // add a method to the ghost and map it to the method in the struct/class
.member("value", &Test::getValue, &Test::setValue);
     // set up a  new namespace for our functions, named test
     // set up a  new namespace for our functions, named test
     nasal::Hash globals_module(globals, c),
     nasal::Hash globals_module(globals, c),
               test = globals_module.createHash("test");
               test = globals_module.createHash("test"); // this is the namespace we'll see and use in Nasal
   
   
   // add an allocator to the test namespace for creating new test objects
   // add an allocator to the test namespace for creating new test objects
  // which will be accessible as test.new()
   test.set("new", &f_newtest);
   test.set("new", &f_newtest);
   
   
   
   
     return naNil(); //we already did all the namespace setup, so we can return naNil() here  
     return naNil(); //we already did all the namespace setup, so we can simply return naNil() here, it's discarded anyways
}
}
</syntaxhighlight>
</syntaxhighlight>

Navigation menu