Howto:Extend Nasal: Difference between revisions

Jump to navigation Jump to search
Re-link lots of things
m (Copyediting)
(Re-link lots of things)
Line 1: Line 1:
{{Template:Nasal Internals}}
{{Nasal Internals}}
This article is dedicated to describing how to write custom C/C++ extension functions in order to extend the [[Nasal]] scripting interpreter in FlightGear, for example in order to expose new or existing FlightGear APIs to the Nasal scripting engine, so that Nasal scripts can access additional FlightGear internals.
This article is dedicated to describing how to write custom C/C++ extension functions in order to ''extend the [[Nasal]] scripting interpreter'' in FlightGear, for example in order to expose new or existing FlightGear APIs to the Nasal scripting engine, so that Nasal scripts can access additional FlightGear internals.
<!-- Some interesting ideas for extending Nasal this way have been collected at [[Proposals:Nasal related]].  Article was deleted 1 July 2014. /Johan G, 12 December 2014 -->
<!-- Some interesting ideas for extending Nasal this way have been collected at [[Proposals:Nasal related]].  Article was deleted 1 July 2014. /Johan G, 12 December 2014 -->


== Status (cppbind) ==
== Status (cppbind) ==
As of 03/2013, this article should be considered depreciated, we have [[Nasal/CppBind|a new C++-based API for exposing C/C++ functions/data structures to Nasal and vice versa]] in {{Git file|gitorious|fg/simgear|next|simgear/nasal/cppbind|pre=$SG_SRC/}}. Usually, there should be no need to use the bare Nasal APIs anymore for exposing functions/data to Nasal or Nasal-space types to C++, except for people working on the '''cppbind''' framework itself.  
As of 03/2013, this article should be considered depreciated, we have [[Nasal/CppBind]], a new C++-based API for exposing C/C++ functions/data structures to Nasal and vice versa in {{simgear file|simgear/nasal/cppbind}}. Usually, there should be no need to use the bare Nasal APIs anymore for exposing functions/data to Nasal or Nasal-space types to C++, except for people working on the '''cppbind''' framework itself.  


The cppbind framework is much more generic and high level than the bare APIs documented here, it includes unit testing support and makes use of modern C++ features like templates and STL support, including SimGear specific types like SGPath/SGGeod etc, its overhead is fairly small (not just performance, but also LoC to create new bindings).
The cppbind framework is much more generic and high level than the bare APIs documented here, it includes unit testing support and makes use of modern C++ features like templates and STL support, including SimGear specific types like SGPath/SGGeod etc, its overhead is fairly small (not just performance, but also LoC to create new bindings).
Line 36: Line 36:
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer and refine existing ones.
If you have any Nasal specific questions, you will want to check out the [[Nasal FAQ]], feel free to ask new questions or help answer and refine existing ones.


All Nasal related articles can be found in the [http://wiki.flightgear.org/index.php/Category:Nasal Nasal category].
All Nasal related articles can be found in [[:Category:Nasal]].


{{Note|FlightGear's version of the Nasal interpreter is maintained in the [http://www.simgear.org SimGear] git repository, inside the {{Git file|gitorious|fg/simgear|next|simgear/nasal|pre=$SG_SRC/}} folder, the most important header file detailing the internal Nasal API is "[http://simgear.org/doxygen/nasal_8h-source.html nasal.h]", you will want to check this out for the latest changes and information.}}
{{Note|FlightGear's version of the Nasal interpreter is maintained in the SimGear git repository, inside the {{simgear file|simgear/nasal}} folder, the most important header file detailing the internal Nasal API is [http://api-docs.freeflightsim.org/simgear/nasal_8h.html nasal.h], you will want to check this out for the latest changes and information.}}


You will probably also want to check out the {{Git file|gitorious|fg/simgear|next|simgear/nasal|pre=$SG_SRC/}} folder for specific examples on using the various Nasal APIs that are not yet covered here completely.
You will probably also want to check out the {{simgear file|simgear/nasal}} folder for specific examples on using the various Nasal APIs that are not yet covered here completely.


{{caution|As of 05/2009, this article is work in progress, and ''none'' of the examples have so far been tested/compiled.  
{{caution|As of 05/2009, this article is work in progress, and ''none'' of the examples have so far been tested/compiled.  
Line 48: Line 48:


== Intro ==
== Intro ==
In FlightGear, the simplest way to add new extension functions is to look at the existing functions in {{Git file|gitorious|fg/flightgear|next|src/Scripting/NasalSys.cxx|747|pre=$FG_SRC/}}.
In FlightGear, the simplest way to add new extension functions is to look at the existing functions at {{flightgear file|src/Scripting/NasalSys.cxx|l=747}}.


There is a static table of function pointers (named funcs[]) referencing extension functions, along with their corresponding names in Nasal: {{Git file|gitorious|fg/flightgear|next|src/Scripting/NasalSys.cxx|482|pre=$FG_SRC/}}
There is a static table of function pointers (named funcs[]) referencing extension functions, along with their corresponding names in Nasal: {{flightgear file|src/Scripting/NasalSys.cxx|l=482}}.
The following is a copy of the extension function list, taken in 12/2014:
The following is a copy of the extension function list, taken in 12/2014:


Line 83: Line 83:
</syntaxhighlight>
</syntaxhighlight>


(Note, as of 06/2012, some of these functions have meanwhile been moved to a different file and are initialized there: NasalPositioned.cxx)  
(Note, as of 06/2012, some of these functions have meanwhile been moved to a different file and are initialized there: {{flightgear file|src/Scripting/NasalPositioned.cxx|t=NasalPositioned.cxx}})  


So, the basic format is "name" (string), function_pointer - whereas "name" refers to the internal name used by Nasal and its scripts, and "function_pointer" has to use the right function signature and is a pointer to the implementation of the Nasal function in C/C++ code space:
So, the basic format is "name" (string), function_pointer - whereas "name" refers to the internal name used by Nasal and its scripts, and "function_pointer" has to use the right function signature and is a pointer to the implementation of the Nasal function in C/C++ code space:
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
// The function signature for an extension function:
// The function signature for an extension function:
typedef naRef (*naCFunction)(naContext ctx, naRef me, int argc, naRef* args);
typedef naRef (*naCFunction)(naContext ctx, naRef me, int argc, naRef* args);
</syntaxhighlight>
</syntaxhighlight>


You will need to add your new extension function to this list of static functions, preferably following the existing naming convention (i.e. "f_" prefix).
You will need to add your new extension function to this list of static functions, preferably following the existing naming convention (i.e. "f_" prefix).


If your extension functions are likely to be fairly low level, and will thus be provided with a more abstract wrapper in Nasal space, these functions should use a prepended undercore ("_"), such as the _fgcommand, _setlistener, _cmdarg and _interpolate functions.
If your extension functions are likely to be fairly low level, and will thus be provided with a more abstract wrapper in Nasal space, these functions should use a prepended undercore ("_"), such as the {{func link|_fgcommand}}, {{func link|_setlistener}}, {{func link|_cmdarg}} and {{func link|_interpolate}} functions.


== Extension function signature ==
== Extension function signature ==
These extension functions look like:
These extension functions look like:
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
  static naRef f_your_function(naContext c, naRef me, int argc, naRef* args)
static naRef f_your_function(naContext c, naRef me, int argc, naRef* args)
  {
{
      // ...
    // ...
  }
}
</syntaxhighlight>
</syntaxhighlight>


Line 111: Line 109:


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
  static naRef f_cool (naContext c, naRef me, int argc, naRef* args)
static naRef f_cool (naContext c, naRef me, int argc, naRef* args)
  {
{
      SG_LOG(SG_GENERAL, SG_ALERT, "Nasal:cool() got executed!");
    SG_LOG(SG_GENERAL, SG_ALERT, "Nasal:cool() got executed!");
      return naNil();
    return naNil();
  }
}
</syntaxhighlight>
</syntaxhighlight>


Line 177: Line 175:
The "me" reference is set if the function was called as a method call on an object (e.g. object.your_function() instead of just your_function(), in which case "me" would be set to the object (Nasal hash)).
The "me" reference is set if the function was called as a method call on an object (e.g. object.your_function() instead of just your_function(), in which case "me" would be set to the object (Nasal hash)).


The naRef objects can be manipulated using the functions in [http://simgear.org/doxygen/nasal_8h-source.html nasal.h].
The naRef objects can be manipulated using the functions in [http://api-docs.freeflightsim.org/simgear/nasal_8h.html nasal.h].
For the latest copy of the file, see: {{Git file|gitorious|fg/simgear|next|simgear/nasal/nasal.h|pre=$SG_SRC/}}
For the latest copy of the file, see {{simgear file|simgear/nasal/nasal.h}}


Basically, you can check the type of the reference with the following naIs*() functions:
Basically, you can check the type of the reference with the following naIs*() functions:
Line 320: Line 318:


== Wrapping C++ classes as Nasal objects with cppbind ==
== Wrapping C++ classes as Nasal objects with cppbind ==
Please see: {{Git file|gitorious|fg/simgear|next|simgear/nasal/cppbind|pre=$SG_SRC/}}
Please see: {{simgear file|simgear/nasal/cppbind}}
<!--
<!--
'''To be written by Hooray & Zakalawe'''
'''To be written by Hooray & Zakalawe'''


For the time being, it's a good idea to take a look at the FGPositioned wrappers for the navdb to see how this is done in Nasal, see [https://gitorious.org/fg/flightgear/blobs/next/src/Scripting/NasalPositioned.cxx $FG_SRC/Scripting/NasalPositioned.cxx].
For the time being, it's a good idea to take a look at the FGPositioned wrappers for the navdb to see how this is done in Nasal, see {{flightgear file|src/Scripting/NasalPositioned.cxx}}.
Also, the implementation of the SGPropertyNode bindings in [https://gitorious.org/fg/flightgear/blobs/next/src/Scripting/nasal-props.cxx nasal-props.cxx] contains additional examples.
Also, the implementation of the SGPropertyNode bindings in {{flightgear file|src/Scripting/nasal-props.cxx}} contains additional examples.
-->
-->
== Passing pointers to Nasal scripts ==
== Passing pointers to Nasal scripts ==

Navigation menu