20,741
edits
| (28 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
{{WIP}} | <!-- {{WIP}} --> | ||
{{Stub}} | {{Stub}} | ||
FlightGear's built-in [[Nasal]] scripting language comes with a set of standard libraries, and can be extended using FlightGear specific APIs. | |||
Exposing simulator internals to scripting space is a fairly common and useful thing, because it enables base package developers to access these internals without having to build FlightGear from source, so the barrier to entry is significantly lower and we've seen an increasing number of novel features purely implemented in scripting space, due to powerful APIs being available to aircraft developers and other base package developers. | |||
FlightGear' | |||
Until FlightGear 2.8, the [[Nasal]] scripting engine only provided a C API to expose such hooks/bindings to scripting space or to expose scripting space data structures back to C/C++. | Until FlightGear 2.8, the [[Nasal]] scripting engine only provided a C API to expose such hooks/bindings to scripting space or to expose scripting space data structures back to C/C++. | ||
Unlike the core Nasal engine itself (which is C), FlightGear however is mostly written and being developed in C++. For quite a while, that meant that the Nasal APIs were a bit low-level, and sometimes also awkward to use when making functions, data structures or objects accessible between C++ and Nasal. | Unlike the core Nasal engine itself (which is C), FlightGear however is mostly written and being developed in C++. For quite a while, that meant that the Nasal APIs were a bit low-level, and sometimes also awkward to use when making functions, data structures or objects accessible between C++ and Nasal. | ||
Thanks to Tom's [[Canvas]] system, there's now a new bindings framework to be found in simgear/nasal/cppbind. This is fully object oriented and supports modern C++ features. | Thanks to development on Tom's [[Canvas]] system, there's now a new bindings framework to be found in [[$SG_SRC]]/simgear/nasal/cppbind. This is fully object oriented and supports modern C++ features by operating through classes and methods with full STL support, abstracting most common operations away. | ||
You will find that most of the "old" code in $FG_SRC/Scripting still uses those old C-APIs for interacting with the Nasal engine. Only the new code, #include | You will find that most of the "old" code in [[$FG_SRC]]/Scripting still uses those old C-APIs for interacting with the Nasal engine. Only the new code, those that <tt>#include <simgear/nasal/cppbind></tt> use boost templates to hide low level details. | ||
Most of the code in the Nasal subsystem itself (FGNasalSys) also still uses the legacy C APIs | Most of the code in the Nasal subsystem itself (FGNasalSys) also still uses the legacy C APIs. You will find the old, low-level APIs explained at [[Howto:Extend Nasal]] - this is just to explain the two approaches, to avoid unnecessary confusion. | ||
The cppbind framework is much more generic and high level than the bare C APIs, cppbind 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 already extensively used by the Canvas system and the NasalPositioned_cppbind bindings, both of which are a good place to look for code examples. | The cppbind framework is much more generic and high level than the bare C APIs, cppbind 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 already extensively used by the Canvas system and the NasalPositioned_cppbind bindings, both of which are a good place to look for code examples. | ||
Meanwhile, we suggest to favor cppbind over the old, low-level, approach, it isn't only much more elegant, but also saves you tons of typing, too - and will do certain error-checking automatically | Meanwhile, we suggest to favor cppbind over the old, low-level, approach, it isn't only much more elegant, but also saves you tons of typing, too - and will do certain error-checking automatically that you would otherwise have to implement manually. | ||
== Worthwhile Targets == | |||
{{Template:Mentored Volunteer Effort | |||
|mentors= Hooray (get in touch to learn more) | |||
|skills=[[Building Flightgear]], [[Developing using CMake]], [[Programming Resources#Programming_-_Background_knowledge|C++]], some [[Nasal]] }} | |||
{{CppBind Ideas}} | |||
== Prerequisites == | |||
* [[Building FlightGear]] | |||
* [[Developing using CMake]] | |||
* [[Programming Resources|C++ experience]] | |||
* [[Nasal|Nasal experience]] | |||
== Objective == | == Objective == | ||
Provide a fully annotated step-by-step introduction to Nasal's cppbind framework. This is mostly based on existing code in SimGear/FlightGear. The cppbind framework itself is to be found $SG_SRC/nasal/cppbind and it's pretty well commented, and makes use of Doxygen strings. If you are already familiar with C++ and SG/FG,, you'll want to check out the unit tests in cppbind_test.cxx. | |||
Provide a fully annotated step-by-step introduction to Nasal's cppbind framework. This is mostly based on existing code in SimGear/FlightGear. The cppbind framework itself is to be found $SG_SRC/nasal/cppbind and it's pretty well commented, and makes use of Doxygen strings. If you are already familiar with C++ and SG/FG,, you'll want to check out the unit tests in cppbind_test.cxx. | |||
This write-up should get you started with the basics of the framework. | This write-up should get you started with the basics of the framework. | ||
| Line 72: | Line 68: | ||
<syntaxhighlight lang="cpp" enclose="div"> | <syntaxhighlight lang="cpp" enclose="div"> | ||
initNasalDemo(_globals, _context); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
| Line 145: | Line 140: | ||
// to call the code, add this to FGNasalSys::init(): | // to call the code, add this to FGNasalSys::init(): | ||
/* | /* | ||
initNasalDemo(_globals, _context); | initNasalDemo(_globals, _context); | ||
*/ | */ | ||
| Line 152: | Line 145: | ||
naRef initNasalDemo(naRef globals, naContext c) | naRef initNasalDemo(naRef globals, naContext c) | ||
{ | { | ||
if(NasalTest::isInit() ) return naNil(); // avoid re-init during reset/re-init | |||
// This only needs to be called once for each ghost, so make sure to use the ::isInit() check in FGNasalSys::init() | // 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!) | ||
| Line 195: | Line 190: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Exposing HLA to Nasal == | == Exposing HLA classes to Nasal == | ||
Here's another stub, this time exposing the simgear::HLAFederate class and a handful of its methods to Nasal space as a Nasal Ghost. Note that the following snippet assumes, that: | Here's another stub, this time exposing the simgear::HLAFederate class and a handful of its methods to Nasal space as a Nasal Ghost. Note that the following snippet assumes, that: | ||
* You configured, built & installed OpenRTI (see [[HLA]] | * You configured, built & installed OpenRTI (see [[HLA]]) | ||
* you configured, built & installed SimGear with -DENABLE_RTI=ON | * you configured, built & installed SimGear with '''-DENABLE_RTI=ON''' | ||
* you configured, built FlightGear with -DENABLE_RTI=ON | * you configured, built FlightGear with '''-DENABLE_RTI=ON''' | ||
In and of itself, this snippet isn't yet particularly useful, especially because we don't want HLA federates to be running inside the main process, but the same HLA bindings could obviously also be used by a standalone Nasal interpreter at some point. So this just serves as an example. To learn more about HLA, please also see [[Developing with HLA]]. | In and of itself, this snippet isn't yet particularly useful, especially because we don't want HLA federates to be running inside the main process, but the same HLA bindings could obviously also be used by a standalone Nasal interpreter at some point. So this just serves as an example. To learn more about HLA, please also see [[Developing with HLA]] and [[Nasal HLA standalone]]. | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||