filter declarations in C++, improve luadoc
This commit is contained in:
parent
c8b7d70ffa
commit
dd27620566
|
@ -14,6 +14,8 @@ echo "# analyzing source.. -> $TMPFILE"
|
||||||
$LLVMINCLUDE -I /usr/include/linux \
|
$LLVMINCLUDE -I /usr/include/linux \
|
||||||
-I libs/ardour -I libs/pbd -I libs/lua -I gtk2_ardour -I libs/timecode \
|
-I libs/ardour -I libs/pbd -I libs/lua -I gtk2_ardour -I libs/timecode \
|
||||||
-I libs/ltc -I libs/evoral \
|
-I libs/ltc -I libs/evoral \
|
||||||
|
-X "_" -X "::" -X "sigc" -X "Atk::" -X "Gdk::" -X "Gtk::" -X "Gio::" \
|
||||||
|
-X "Glib::" -X "Pango::" -X "luabridge::" \
|
||||||
libs/ardour/ardour/* libs/pbd/pbd/* \
|
libs/ardour/ardour/* libs/pbd/pbd/* \
|
||||||
gtk2_ardour/*.h \
|
gtk2_ardour/*.h \
|
||||||
/usr/include/cairomm-1.0/cairomm/context.h \
|
/usr/include/cairomm-1.0/cairomm/context.h \
|
||||||
|
@ -28,22 +30,12 @@ php << EOF
|
||||||
\$api = array ();
|
\$api = array ();
|
||||||
foreach (json_decode (\$json, true) as \$a) {
|
foreach (json_decode (\$json, true) as \$a) {
|
||||||
if (!isset (\$a['decl'])) { continue; }
|
if (!isset (\$a['decl'])) { continue; }
|
||||||
if (empty (\$a['decl'])) { continue; }
|
|
||||||
if (\$a['decl'] == '::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 1) == '_') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 2) == '::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 4) == 'sigc') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 5) == 'Atk::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 5) == 'Gdk::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 5) == 'Gtk::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 5) == 'Gio::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 6) == 'Glib::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 7) == 'Pango::') { continue; }
|
|
||||||
if (substr (\$a['decl'], 0, 11) == 'luabridge::') { continue; }
|
|
||||||
|
|
||||||
\$a['decl'] = str_replace ('size_t', 'unsigned long', \$a['decl']);
|
\$a['decl'] = str_replace ('size_t', 'unsigned long', \$a['decl']);
|
||||||
\$a['decl'] = str_replace ('uint32_t', 'unsigned int', \$a['decl']);
|
\$a['decl'] = str_replace ('uint32_t', 'unsigned int', \$a['decl']);
|
||||||
|
\$a['decl'] = str_replace ('int32_t', 'int', \$a['decl']);
|
||||||
\$a['decl'] = str_replace ('framepos_t', 'long', \$a['decl']);
|
\$a['decl'] = str_replace ('framepos_t', 'long', \$a['decl']);
|
||||||
|
\$a['decl'] = str_replace ('framecnt_t', 'long', \$a['decl']);
|
||||||
\$a['decl'] = str_replace ('frameoffset_t', 'long', \$a['decl']);
|
\$a['decl'] = str_replace ('frameoffset_t', 'long', \$a['decl']);
|
||||||
\$a['decl'] = str_replace ('int64_t', 'long', \$a['decl']);
|
\$a['decl'] = str_replace ('int64_t', 'long', \$a['decl']);
|
||||||
\$a['decl'] = str_replace ('uint8_t', 'unsigned char', \$a['decl']);
|
\$a['decl'] = str_replace ('uint8_t', 'unsigned char', \$a['decl']);
|
||||||
|
@ -57,7 +49,7 @@ foreach (json_decode (\$json, true) as \$a) {
|
||||||
\$a['decl'] = str_replace ('const unsigned long', 'unsigned long', \$a['decl']);
|
\$a['decl'] = str_replace ('const unsigned long', 'unsigned long', \$a['decl']);
|
||||||
\$canon = str_replace (' *', '*', \$a['decl']);
|
\$canon = str_replace (' *', '*', \$a['decl']);
|
||||||
\$api[\$canon] = \$a;
|
\$api[\$canon] = \$a;
|
||||||
}
|
}
|
||||||
\$jout = array ();
|
\$jout = array ();
|
||||||
foreach (\$api as \$k => \$a) {
|
foreach (\$api as \$k => \$a) {
|
||||||
\$jout[] = \$a;
|
\$jout[] = \$a;
|
||||||
|
|
|
@ -23,9 +23,49 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <map>
|
||||||
#include <clang-c/Index.h>
|
#include <clang-c/Index.h>
|
||||||
#include <clang-c/Documentation.h>
|
#include <clang-c/Documentation.h>
|
||||||
|
|
||||||
|
struct dox2js {
|
||||||
|
dox2js () : clang_argc (2), clang_argv (0), excl_argc (0), excl_argv (0)
|
||||||
|
{
|
||||||
|
excl_argv = (char**) calloc (1, sizeof (char*));
|
||||||
|
clang_argv = (char**) malloc (clang_argc * sizeof (char*));
|
||||||
|
clang_argv[0] = strdup ("-x");
|
||||||
|
clang_argv[1] = strdup ("c++");
|
||||||
|
}
|
||||||
|
|
||||||
|
~dox2js () {
|
||||||
|
for (int i = 0; i < clang_argc; ++i) {
|
||||||
|
free (clang_argv[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0; excl_argv[i]; ++i) {
|
||||||
|
free (excl_argv[i]);
|
||||||
|
}
|
||||||
|
free (clang_argv);
|
||||||
|
free (excl_argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_clang_arg (const char *a) {
|
||||||
|
clang_argv = (char**) realloc (clang_argv, (clang_argc + 2) * sizeof (char*));
|
||||||
|
clang_argv[clang_argc++] = strdup ("-I");
|
||||||
|
clang_argv[clang_argc++] = strdup (a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_exclude (const char *a) {
|
||||||
|
excl_argv = (char**) realloc (excl_argv, (excl_argc + 2) * sizeof (char*));
|
||||||
|
excl_argv[excl_argc++] = strdup (a);
|
||||||
|
excl_argv[excl_argc] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clang_argc;
|
||||||
|
char** clang_argv;
|
||||||
|
int excl_argc;
|
||||||
|
char** excl_argv;
|
||||||
|
std::map <std::string, std::string> results;
|
||||||
|
};
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
kind_to_txt (CXCursor cursor)
|
kind_to_txt (CXCursor cursor)
|
||||||
{
|
{
|
||||||
|
@ -69,20 +109,37 @@ escape_json (const std::string &s)
|
||||||
return o.str ();
|
return o.str ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void recurse_parents (CXCursor cr) {
|
static std::string
|
||||||
|
recurse_parents (CXCursor cr) {
|
||||||
|
std::string rv;
|
||||||
CXCursor pc = clang_getCursorSemanticParent (cr);
|
CXCursor pc = clang_getCursorSemanticParent (cr);
|
||||||
if (CXCursor_TranslationUnit == clang_getCursorKind (pc)) {
|
if (CXCursor_TranslationUnit == clang_getCursorKind (pc)) {
|
||||||
return;
|
return rv;
|
||||||
}
|
}
|
||||||
if (!clang_Cursor_isNull (pc)) {
|
if (!clang_Cursor_isNull (pc)) {
|
||||||
recurse_parents (pc);
|
rv += recurse_parents (pc);
|
||||||
printf ("%s::", clang_getCString (clang_getCursorDisplayName (pc)));
|
rv += clang_getCString (clang_getCursorDisplayName (pc));
|
||||||
|
rv += "::";
|
||||||
}
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
check_excludes (const std::string& decl, CXClientData d) {
|
||||||
|
struct dox2js* dj = (struct dox2js*) d;
|
||||||
|
char** excl = dj->excl_argv;
|
||||||
|
for (int i = 0; excl[i]; ++i) {
|
||||||
|
if (decl.compare (0, strlen (excl[i]), excl[i]) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum CXChildVisitResult
|
static enum CXChildVisitResult
|
||||||
traverse (CXCursor cr, CXCursor /*parent*/, CXClientData)
|
traverse (CXCursor cr, CXCursor /*parent*/, CXClientData d)
|
||||||
{
|
{
|
||||||
|
struct dox2js* dj = (struct dox2js*) d;
|
||||||
CXComment c = clang_Cursor_getParsedComment (cr);
|
CXComment c = clang_Cursor_getParsedComment (cr);
|
||||||
|
|
||||||
if (clang_Comment_getKind (c) != CXComment_Null
|
if (clang_Comment_getKind (c) != CXComment_Null
|
||||||
|
@ -90,45 +147,48 @@ traverse (CXCursor cr, CXCursor /*parent*/, CXClientData)
|
||||||
&& 0 != strlen (kind_to_txt (cr))
|
&& 0 != strlen (kind_to_txt (cr))
|
||||||
) {
|
) {
|
||||||
|
|
||||||
printf ("{ \"decl\" : \"");
|
|
||||||
recurse_parents (cr);
|
|
||||||
|
|
||||||
// TODO: resolve typedef enum { .. } name;
|
// TODO: resolve typedef enum { .. } name;
|
||||||
// use clang_getCursorDefinition (clang_getCanonicalCursor (cr)) ??
|
// use clang_getCursorDefinition (clang_getCanonicalCursor (cr)) ??
|
||||||
printf ("%s\",\n", clang_getCString (clang_getCursorDisplayName (cr)));
|
std::string decl = recurse_parents (cr);
|
||||||
|
decl += clang_getCString (clang_getCursorDisplayName (cr));
|
||||||
|
|
||||||
if (clang_Cursor_isVariadic (cr)) {
|
if (decl.empty () || check_excludes (decl, d)) {
|
||||||
printf (" \"variadic\" : true,\n");
|
return CXChildVisit_Recurse;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf (" \"kind\" : \"%s\",\n", kind_to_txt (cr));
|
std::ostringstream o;
|
||||||
|
o << "{ \"decl\" : \"" << decl << "\",\n";
|
||||||
|
|
||||||
|
if (clang_Cursor_isVariadic (cr)) {
|
||||||
|
o << " \"variadic\" : true,\n";
|
||||||
|
}
|
||||||
|
|
||||||
CXSourceLocation loc = clang_getCursorLocation (cr);
|
CXSourceLocation loc = clang_getCursorLocation (cr);
|
||||||
CXFile file; unsigned line, col, off;
|
CXFile file; unsigned line, col, off;
|
||||||
clang_getFileLocation (loc, &file, &line, &col, &off);
|
clang_getFileLocation (loc, &file, &line, &col, &off);
|
||||||
|
|
||||||
printf (" \"src\" : \"%s:%d\",\n",
|
o << " \"kind\" : \"" << kind_to_txt (cr) << "\",\n"
|
||||||
clang_getCString (clang_getFileName (file)), line);
|
<< " \"src\" : \"" << clang_getCString (clang_getFileName (file)) << ":" << line << "\",\n"
|
||||||
|
<< " \"doc\" : \"" << escape_json (clang_getCString (clang_FullComment_getAsHTML (c))) << "\"\n"
|
||||||
|
<< "},\n";
|
||||||
|
|
||||||
printf (" \"doc\" : \"%s\"\n",
|
dj->results[decl] = o.str ();
|
||||||
escape_json (clang_getCString (clang_FullComment_getAsHTML (c))).c_str ());
|
|
||||||
printf ("},\n");
|
|
||||||
}
|
}
|
||||||
return CXChildVisit_Recurse;
|
return CXChildVisit_Recurse;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_file (int argc, char **args, const char *fn)
|
process_file (const char* fn, struct dox2js *dj)
|
||||||
{
|
{
|
||||||
CXIndex index = clang_createIndex (0, 0);
|
CXIndex index = clang_createIndex (0, 0);
|
||||||
CXTranslationUnit tu = clang_createTranslationUnitFromSourceFile (index, fn, argc, args, 0, 0);
|
CXTranslationUnit tu = clang_createTranslationUnitFromSourceFile (index, fn, dj->clang_argc, dj->clang_argv, 0, 0);
|
||||||
|
|
||||||
if (tu == NULL) {
|
if (tu == NULL) {
|
||||||
fprintf (stderr, "Cannot create translation unit for src: %s\n", fn);
|
fprintf (stderr, "Cannot create translation unit for src: %s\n", fn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clang_visitChildren (clang_getTranslationUnitCursor (tu), traverse, 0);
|
clang_visitChildren (clang_getTranslationUnitCursor (tu), traverse, (CXClientData) dj);
|
||||||
|
|
||||||
clang_disposeTranslationUnit (tu);
|
clang_disposeTranslationUnit (tu);
|
||||||
clang_disposeIndex (index);
|
clang_disposeIndex (index);
|
||||||
|
@ -138,23 +198,23 @@ static void
|
||||||
usage (int status)
|
usage (int status)
|
||||||
{
|
{
|
||||||
printf ("doxy2json - extract doxygen doc from C++ headers.\n\n");
|
printf ("doxy2json - extract doxygen doc from C++ headers.\n\n");
|
||||||
fprintf (stderr, "Usage: dox2json [-I path]* <filename> [filename]*\n");
|
fprintf (stderr, "Usage: dox2json [-I path]* [-X exclude]* <filename> [filename]*\n");
|
||||||
exit (status);
|
exit (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char** argv)
|
||||||
{
|
{
|
||||||
int cnt = 2;
|
struct dox2js dj;
|
||||||
char **args = (char**) malloc (cnt * sizeof (char*));
|
|
||||||
args[0] = strdup ("-x");
|
bool report_progress = false;
|
||||||
args[1] = strdup ("c++");
|
|
||||||
int c;
|
int c;
|
||||||
while (EOF != (c = getopt (argc, argv, "I:"))) {
|
while (EOF != (c = getopt (argc, argv, "I:X:"))) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'I':
|
case 'I':
|
||||||
args = (char**) realloc (args, (cnt + 2) * sizeof (char*));
|
dj.add_clang_arg (optarg);
|
||||||
args[cnt++] = strdup ("-I");
|
break;
|
||||||
args[cnt++] = strdup (optarg);
|
case 'X':
|
||||||
|
dj.add_exclude (optarg);
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
usage (0);
|
usage (0);
|
||||||
|
@ -168,16 +228,26 @@ int main (int argc, char **argv)
|
||||||
usage (EXIT_FAILURE);
|
usage (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf ("[\n");
|
const int total = (argc - optind);
|
||||||
|
if (total > 6) {
|
||||||
|
report_progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = optind; i < argc; ++i) {
|
for (int i = optind; i < argc; ++i) {
|
||||||
process_file (cnt, args, argv[i]);
|
process_file (argv[i], &dj);
|
||||||
|
if (report_progress) {
|
||||||
|
fprintf (stderr, "progress: %4.1f%% [%4d / %4d] decl: %ld \r",
|
||||||
|
100.f * (1.f + i - optind) / (float)total, i - optind, total,
|
||||||
|
dj.results.size ());
|
||||||
|
fflush (stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("[\n");
|
||||||
|
for (std::map <std::string, std::string>::const_iterator i = dj.results.begin (); i != dj.results.end (); ++i) {
|
||||||
|
printf ("%s\n", (*i).second.c_str ());
|
||||||
}
|
}
|
||||||
printf ("{} ]\n");
|
printf ("{} ]\n");
|
||||||
|
|
||||||
for (int i = 0; i < cnt; ++i) {
|
|
||||||
free (args[i]);
|
|
||||||
}
|
|
||||||
free (args);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -601,10 +601,15 @@ h2.enum { background-color: #aaaaaa; }
|
||||||
h2.pointerclass { background-color: #eeaa66; }
|
h2.pointerclass { background-color: #eeaa66; }
|
||||||
h2.array { background-color: #66aaee; }
|
h2.array { background-color: #66aaee; }
|
||||||
h2.opaque { background-color: #6666aa; }
|
h2.opaque { background-color: #6666aa; }
|
||||||
|
p { text-align: justify; }
|
||||||
p.cdecl { text-align: right; float:right; font-size:90%; margin:0; padding: 0 0 0 1em;}
|
p.cdecl { text-align: right; float:right; font-size:90%; margin:0; padding: 0 0 0 1em;}
|
||||||
ul.classindex { columns: 2; -webkit-columns: 2; -moz-columns: 2; }
|
ul.classindex { columns: 2; -webkit-columns: 2; -moz-columns: 2; }
|
||||||
div.clear { clear:both; }
|
div.clear { clear:both; }
|
||||||
p.classinfo { margin: .25em 0;}
|
p.classinfo { margin: .25em 0;}
|
||||||
|
div.code { width:80%; margin:.5em auto; }
|
||||||
|
div.code div { width:45%; }
|
||||||
|
div.code pre { line-height: 1.2em; margin: .25em 0; }
|
||||||
|
div.code samp { color: green; font-weight: bold; background-color: #eee; }
|
||||||
div.classdox { padding: .1em 1em;}
|
div.classdox { padding: .1em 1em;}
|
||||||
div.classdox p { margin: .5em 0 .5em .6em;}
|
div.classdox p { margin: .5em 0 .5em .6em;}
|
||||||
div.classdox p { margin: .5em 0 .5em .6em;}
|
div.classdox p { margin: .5em 0 .5em .6em;}
|
||||||
|
@ -615,7 +620,7 @@ table.classmembers th { text-align:left; border-bottom:1px solid black; pad
|
||||||
table.classmembers td.def { text-align:right; padding-right:.5em; white-space: nowrap;}
|
table.classmembers td.def { text-align:right; padding-right:.5em; white-space: nowrap;}
|
||||||
table.classmembers td.decl { text-align:left; padding-left:.5em; white-space: nowrap; }
|
table.classmembers td.decl { text-align:left; padding-left:.5em; white-space: nowrap; }
|
||||||
table.classmembers td.doc { text-align:left; padding-left:.6em; line-height: 1.2em; font-size:80%;}
|
table.classmembers td.doc { text-align:left; padding-left:.6em; line-height: 1.2em; font-size:80%;}
|
||||||
table.classmembers td.doc div.dox {background-color:#ddd; padding: .1em 1em;}
|
table.classmembers td.doc div.dox {background-color:#eee; padding: .1em 1em;}
|
||||||
table.classmembers td.doc p { margin: .5em 0; }
|
table.classmembers td.doc p { margin: .5em 0; }
|
||||||
table.classmembers td.doc p.para-brief { font-size:120%; }
|
table.classmembers td.doc p.para-brief { font-size:120%; }
|
||||||
table.classmembers td.doc p.para-returns { font-size:120%; }
|
table.classmembers td.doc p.para-returns { font-size:120%; }
|
||||||
|
@ -626,7 +631,7 @@ table.classmembers span.em { font-style: italic;}
|
||||||
span.functionname abbr { text-decoration:none; cursor:default;}
|
span.functionname abbr { text-decoration:none; cursor:default;}
|
||||||
div.header {text-align:center;}
|
div.header {text-align:center;}
|
||||||
div.header h1 {margin:0;}
|
div.header h1 {margin:0;}
|
||||||
div.header p {margin:.25em;}
|
div.header p {margin:.25em; text-align:center;}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -664,12 +669,90 @@ Tracks contain specifics. For Example a track <em>has-a</em> diskstream (for fil
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Operations are performed on objects. One gets a reference to an object and then calls a method.
|
Operations are performed on objects. One gets a reference to an object and then calls a method.
|
||||||
e.g obj = Session:route_by_name("Audio") obj:set_name("Guitar")
|
e.g <code>obj = Session:route_by_name("Audio") obj:set_name("Guitar")</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Object lifetimes are managed by the Session. Most Objects cannot be directly created, but one asks the Session to create or destroy them. This is mainly due to realtime constrains:
|
Object lifetimes are managed by the Session. Most Objects cannot be directly created, but one asks the Session to create or destroy them. This is mainly due to realtime constrains:
|
||||||
you cannot simply remove a track that is currently processing audio. There are various <em>factory</em> methods for object creation or removal.
|
you cannot simply remove a track that is currently processing audio. There are various <em>factory</em> methods for object creation or removal.
|
||||||
</p>
|
</p>
|
||||||
|
<h2>Pass by Reference</h2>
|
||||||
|
<p>
|
||||||
|
Since lua functions are closures, C++ methods that pass arguments by reference cannot be used as-is.
|
||||||
|
All parameters passed to a C++ method which uses references are returned as Lua Table.
|
||||||
|
If the C++ method also returns a value it is prefixed. Two parameters are returned: the value and a Lua Table holding the parameters.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<div style="float:left;">C++
|
||||||
|
|
||||||
|
<pre><code class="cxx">void set_ref (int& var, long& val)
|
||||||
|
{
|
||||||
|
printf ("%d %ld\n", var, val);
|
||||||
|
var = 5;
|
||||||
|
val = 7;
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="float:right;">Lua
|
||||||
|
|
||||||
|
<pre><code class="lua">local var = 0;
|
||||||
|
ref = set_ref (var, 2);
|
||||||
|
-- output from C++ printf()
|
||||||
|
</code><samp class="lua">0 2</samp><code>
|
||||||
|
-- var is still 0 here
|
||||||
|
print (ref[1], ref[2])
|
||||||
|
</code><samp class="lua">5 7</samp></pre>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clear"></div>
|
||||||
|
<div class="code">
|
||||||
|
<div style="float:left;">
|
||||||
|
|
||||||
|
<pre><code class="cxx">int set_ref2 (int &var, std::string unused)
|
||||||
|
{
|
||||||
|
var = 5;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="float:right;">
|
||||||
|
<pre><code class="lua">rv, ref = set_ref2 (0, "hello");
|
||||||
|
print (rv, ref[1], ref[2])
|
||||||
|
</code><samp class="lua">3 5 hello</samp></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clear"></div>
|
||||||
|
|
||||||
|
<h2>Pointer Classes</h2>
|
||||||
|
<p>
|
||||||
|
Libardour makes extensive use of reference counted <code>boost::shared_ptr</code> to manage lifetimes.
|
||||||
|
The Lua bindings provide a complete abstration of this. There are no pointers in lua.
|
||||||
|
For example a <?=typelink('ARDOUR:Route')?> is a pointer in C++, but lua functions operate on it like it was a class instance.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<code>shared_ptr</code> are reference counted. Once assigned to a lua variable, the C++ object will be kept and remains valid.
|
||||||
|
It is good practice to assign references to lua <code>local</code> variables or reset the variable to <code>nil</code> to drop the ref.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
All pointer classes have a <code>isnil ()</code> method. This is for two cases:
|
||||||
|
Construction may fail. e.g. <code><?=typelink('ARDOUR:LuaAPI')?>.newplugin()</code>
|
||||||
|
may not be able to find the given plugin and hence cannot create an object.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The second case if for <code>boost::weak_ptr</code>. As opposed to <code>boost::shared_ptr</code> weak-pointers are not reference counted.
|
||||||
|
The object may vanish at any time.
|
||||||
|
If lua code calls a method on a nil object, the interpreter will raise an exception and the script will not continue.
|
||||||
|
This is not unlike <code>a = nil a:test()</code> which results in en error "<em>attempt to index a nil value</em>".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
From the lua side of things there is no distinction between weak and shared pointers. They behave identically.
|
||||||
|
Below they're inidicated in orange and have an arrow to indicate the pointer type.
|
||||||
|
Pointer Classes cannot be created in lua scripts. It always requires a call to C++ to create the Object and obtain a reference to it.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
echo '<h1 id="h_classes">Class Documentation</h1>'.NL;
|
echo '<h1 id="h_classes">Class Documentation</h1>'.NL;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user