Nasal/CppBind: Difference between revisions

Jump to navigation Jump to search
m
→‎Getting started: make it build
m (→‎Getting started: make it build)
Line 17: Line 17:


Open $FG_SRC/Scripting/CMakeLists.txt and add these entries to the SOURCES/HEADER section respectively:
Open $FG_SRC/Scripting/CMakeLists.txt and add these entries to the SOURCES/HEADER section respectively:
* NasalTest.cxx (SOURCES)
* NasalDemo.cxx (SOURCES)
* NasalTest.hxx (HEADERS)
* NasalDemo.hxx (HEADERS)


Next, create the NasalTest.cxx source file:
Next, create the NasalDemo.cxx source file:
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
// $FG_SRC/Scripting/NasalTest.cxx
// $FG_SRC/Scripting/NasalDemo.cxx
 
#include <simgear/nasal/cppbind/from_nasal.hxx>
#include <simgear/nasal/cppbind/from_nasal.hxx>
#include <simgear/nasal/cppbind/to_nasal.hxx>
#include <simgear/nasal/cppbind/to_nasal.hxx>
Line 29: Line 29:
#include <simgear/nasal/cppbind/Ghost.hxx>
#include <simgear/nasal/cppbind/Ghost.hxx>
   
   
# 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 x,y,z;
Line 36: Line 36:
  }
  }
};
};
 
// 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
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 between C++  <-> Nasal
 
naRef to_nasal_helper(naContext c, Test *src)
naRef to_nasal_helper(naContext c, Test *src)
   {  
   {  
     NasalTest_ptr ptr(src); // set up a smart pointer wrapping src
     Test_ptr ptr(src); // set up a smart pointer wrapping src
     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
   }
   }
 
Test*
Test*
from_nasal_helper(naContext c, naRef ref, const Test*)
from_nasal_helper(naContext c, naRef ref, const Test*)
   {
   {  
       NasalTest::create(c, ref); // create a new Nasal Ghost
       return (Test*) naGhost_ptr(ref);
   }
   }
 
 
 
// add this to FGNasalSys::init():
// add this to FGNasalSys::init():
/*
/*
  extern initNasalTest(naRef globals, naContext c); // or add this to the header  
  extern initNasalDemo(naRef globals, naContext c); // or add it to the header  
  initNasalTest(_globals, _context);
 
  if( !NasalDemo::isInit() )
initNasalDemo(_globals, _context);
*/
*/
 
static naRef f_newtest(const nasal::CallContext& ctx)
static naRef f_newtest(const nasal::CallContext& ctx)
{
{
Line 72: Line 74:
   t->z = 300;
   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 );
}
}
 
 
// 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()
naRef initNasalTest(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
     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
 
     // 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");
 
   // add an allocator to the test namespace for creating new test objects
   // add an allocator to the test namespace for creating new test objects
   test.set("new", &f_new_test);
   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 return naNil() here  
}
}
</syntaxhighlight>
</syntaxhighlight>


== Testing the whole thing ==
Fire up the Nasal console, and run this:
Fire up the Nasal console, and run this:
<syntaxhighlight lang="nasal">
<syntaxhighlight lang="nasal">
# inspect the test namespace
# inspect the test namespace
debug.dump( test );
debug.dump( test );
# inspect the result of running our allocator function
# inspect the result of running our allocator function
debug.dump( var t=test.new() );
debug.dump( var t=test.new() );
 
# dump the x,y,z members to the console
# dump the x,y,z members to the console
foreach(var e; ['x','y','z']
foreach(var e; ['x','y','z'])
  print (t[e]);
print ( t[e] );
 
# run the hello method
# run the hello method
e.hello();
var t = test.new();
t.hello();
</syntaxhighlight>
</syntaxhighlight>


Navigation menu