Various and sundry updates for the Pike module.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@4758 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
7ac6270fb8
commit
c478c13cf0
6 changed files with 147 additions and 59 deletions
|
|
@ -1,13 +1,33 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>SWIG and Pike</title>
|
||||
<meta http-equiv="content-type"
|
||||
content="text/html; charset=ISO-8859-1">
|
||||
<title>SWIG and Pike</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SWIG and Pike<br>
|
||||
</h1>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
<a name="n1"></a><H1>5 SWIG and Pike</H1>
|
||||
<!-- INDEX -->
|
||||
<ul>
|
||||
<li><a href="#n2">Preliminaries</a>
|
||||
<ul>
|
||||
<li><a href="#n3">Running SWIG</a>
|
||||
<li><a href="#n4">Getting the right header files</a>
|
||||
<li><a href="#n5">Using your module</a>
|
||||
</ul>
|
||||
<li><a href="#n6">Basic C/C++ Mapping</a>
|
||||
<ul>
|
||||
<li><a href="#n7">Modules</a>
|
||||
<li><a href="#n8">Functions</a>
|
||||
<li><a href="#n9">Global variables</a>
|
||||
<li><a href="#n10">Constants and enumerated types</a>
|
||||
<li><a href="#n11">Constructors and Destructors</a>
|
||||
<li><a href="#n12">Static Members</a>
|
||||
</ul>
|
||||
</ul>
|
||||
<!-- INDEX -->
|
||||
|
||||
|
||||
|
||||
This chapter describes SWIG support for Pike. As of this writing, the
|
||||
SWIG Pike module is still under development and is not considered
|
||||
ready for prime time. The Pike module is being developed against the
|
||||
|
|
@ -19,8 +39,12 @@ are covered in less depth than in earlier chapters. At the very
|
|||
least, make sure you read the "<a
|
||||
href="file:///home/jlj/src/SWIG/Doc/Manual/SWIG.html">SWIG Basics</a>"
|
||||
chapter.<br>
|
||||
<h2>Preliminaries</h2>
|
||||
<h3>Running SWIG</h3>
|
||||
<a name="n2"></a><H2>5.1 Preliminaries</H2>
|
||||
|
||||
|
||||
<a name="n3"></a><H3>5.1.1 Running SWIG</H3>
|
||||
|
||||
|
||||
Suppose that you defined a SWIG module such as the following:
|
||||
<blockquote>
|
||||
<pre>%module example<br><br>%{<br>#include "example.h"<br>%}<br><br>int fact(int n);<br></pre>
|
||||
|
|
@ -46,7 +70,9 @@ can use the <tt>-o</tt> option:
|
|||
<blockquote>
|
||||
<pre>$ <b>swig -pike -o pseudonym.c example.i</b><br></pre>
|
||||
</blockquote>
|
||||
<h3>Getting the right header files</h3>
|
||||
<a name="n4"></a><H3>5.1.2 Getting the right header files</H3>
|
||||
|
||||
|
||||
In order to compile the C/C++ wrappers, the compiler needs to know the
|
||||
path to the Pike header files. These files are usually contained in a
|
||||
directory such as
|
||||
|
|
@ -59,7 +85,9 @@ location of these files, so you may need to hunt around for them.
|
|||
You're looking for files with the names <tt>global.h</tt>, <tt>program.h</tt>
|
||||
and so on.
|
||||
|
||||
<h3>Using your module</h3>
|
||||
<a name="n5"></a><H3>5.1.3 Using your module</H3>
|
||||
|
||||
|
||||
To use your module, simply use Pike's <tt>import</tt> statement:
|
||||
|
||||
<blockquote><pre>
|
||||
|
|
@ -70,16 +98,21 @@ Pike v7.4 release 10 running Hilfe v3.5 (Incremental Pike Frontend)
|
|||
(1) Result: 24
|
||||
</pre></blockquote>
|
||||
|
||||
<h2>Basic C/C++ Mapping</h2>
|
||||
<a name="n6"></a><H2>5.2 Basic C/C++ Mapping</H2>
|
||||
|
||||
|
||||
<a name="n7"></a><H3>5.2.1 Modules</H3>
|
||||
|
||||
|
||||
<h3>Modules</h3>
|
||||
All of the code for a given SWIG module is wrapped into a single Pike
|
||||
module. Since the name of the shared library that implements your
|
||||
module ultimately determines the module's name (as far as Pike is
|
||||
concerned), SWIG's <tt>%module</tt> directive doesn't really have any
|
||||
significance.
|
||||
|
||||
<h3>Functions</h3>
|
||||
<a name="n8"></a><H3>5.2.2 Functions</H3>
|
||||
|
||||
|
||||
Global functions are wrapped as new Pike built-in functions. For
|
||||
example,
|
||||
|
||||
|
|
@ -98,7 +131,8 @@ exactly as you'd expect it to:
|
|||
(1) Result: 24
|
||||
</pre></blockquote>
|
||||
|
||||
<h3>Global variables</h3>
|
||||
<a name="n9"></a><H3>5.2.3 Global variables</H3>
|
||||
|
||||
|
||||
Global variables are currently wrapped as a pair of of functions, one to get
|
||||
the current value of the variable and another to set it. For example, the
|
||||
|
|
@ -122,8 +156,38 @@ will result in two functions, <tt>Foo_get()</tt> and <tt>Foo_set()</tt>:
|
|||
(3) Result: 3.141590
|
||||
</pre></blockquote>
|
||||
|
||||
<h3>Constants and enumerated types</h3>
|
||||
<a name="n10"></a><H3>5.2.4 Constants and enumerated types</H3>
|
||||
|
||||
|
||||
Enumerated types in C/C++ declarations are wrapped as Pike constants,
|
||||
not as Pike enums.
|
||||
|
||||
<a name="n11"></a><H3>5.2.5 Constructors and Destructors</H3>
|
||||
|
||||
|
||||
Constructors are wrapped as <tt>create()</tt> methods, and destructors are
|
||||
wrapped as <tt>destroy()</tt> methods, for Pike classes.
|
||||
|
||||
<a name="n12"></a><H3>5.2.6 Static Members</H3>
|
||||
|
||||
|
||||
Since Pike doesn't support static methods or data for Pike classes, static
|
||||
member functions in your C++ classes are wrapped as regular functions and
|
||||
static member variables are wrapped as pairs of functions (one to get the
|
||||
value of the static member variable, and another to set it). The names of
|
||||
these functions are prepended with the name of the class.
|
||||
For example, given this C++ class declaration:
|
||||
|
||||
<blockquote><pre>
|
||||
class Shape
|
||||
{
|
||||
public:
|
||||
static void print();
|
||||
static int nshapes;
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
SWIG will generate a <tt>Shape_print()</tt> method that invokes the static
|
||||
<tt>Shape::print()</tt> member function, as well as a pair of methods,
|
||||
<tt>Shape_nshapes_get()</tt> and <tt>Shape_nshapes_set()</tt>, to get and set
|
||||
the value of <tt>Shape::nshapes</tt>.
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
# see top-level Makefile.in
|
||||
class
|
||||
constants
|
||||
enum
|
||||
simple
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ int Shape::nshapes = 0;
|
|||
|
||||
// Constructor
|
||||
Shape::Shape() {
|
||||
// printf("Shape::Shape(), this = 0x%08x\n", this);
|
||||
nshapes++;
|
||||
}
|
||||
|
||||
|
|
@ -23,26 +22,25 @@ void Shape::move(double dx, double dy) {
|
|||
|
||||
// Destructor
|
||||
Shape::~Shape() {
|
||||
// printf("Shape::~Shape(), this = 0x%08x\n", this);
|
||||
nshapes--;
|
||||
}
|
||||
|
||||
// Circle area
|
||||
double Circle::area() {
|
||||
double Circle::area() const {
|
||||
return M_PI*radius*radius;
|
||||
}
|
||||
|
||||
// Circle perimeter
|
||||
double Circle::perimeter() {
|
||||
double Circle::perimeter() const {
|
||||
return 2*M_PI*radius;
|
||||
}
|
||||
|
||||
// Square area
|
||||
double Square::area() {
|
||||
double Square::area() const {
|
||||
return width*width;
|
||||
}
|
||||
|
||||
// Square perimeter
|
||||
double Square::perimeter() {
|
||||
double Square::perimeter() const {
|
||||
return 4*width;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ public:
|
|||
virtual ~Shape();
|
||||
double x, y;
|
||||
void move(double dx, double dy);
|
||||
virtual double area(void) = 0;
|
||||
virtual double perimeter(void) = 0;
|
||||
virtual double area() const = 0;
|
||||
virtual double perimeter() const = 0;
|
||||
static int nshapes;
|
||||
};
|
||||
|
||||
|
|
@ -16,8 +16,8 @@ private:
|
|||
double radius;
|
||||
public:
|
||||
Circle(double r) : radius(r) { };
|
||||
virtual double area(void);
|
||||
virtual double perimeter(void);
|
||||
virtual double area() const;
|
||||
virtual double perimeter() const;
|
||||
};
|
||||
|
||||
class Square : public Shape {
|
||||
|
|
@ -25,8 +25,8 @@ private:
|
|||
double width;
|
||||
public:
|
||||
Square(double w) : width(w) { };
|
||||
virtual double area(void);
|
||||
virtual double perimeter(void);
|
||||
virtual double area() const;
|
||||
virtual double perimeter() const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,55 +6,47 @@ int main()
|
|||
|
||||
write("Creating some objects:\n");
|
||||
Circle c = Circle(10.0);
|
||||
// write(" Created circle " + (string) c + ".\n");
|
||||
write(" Created circle.\n");
|
||||
Square s = Square(10.0);
|
||||
// write(" Created square " + (string) s + ".\n");
|
||||
write(" Created square.\n");
|
||||
|
||||
// ----- Access a static member -----
|
||||
|
||||
// write("\nA total of " + Shape->nshapes + " shapes were created\n");
|
||||
write("\nA total of " + Shape_nshapes_get() + " shapes were created\n");
|
||||
|
||||
// ----- Member data access -----
|
||||
|
||||
// Set the location of the object
|
||||
|
||||
// c->x = 20.0;
|
||||
// c->y = 30.0;
|
||||
c->x_set(20.0);
|
||||
c->y_set(30.0);
|
||||
|
||||
// s->x = -10.0;
|
||||
// s->y = 5.0;
|
||||
s->x_set(-10.0);
|
||||
s->y_set(5.0);
|
||||
|
||||
write("\nHere is their current position:\n");
|
||||
// write(sprintf(" Circle = (%f, %f)\n", c->x, c->y));
|
||||
// write(sprintf(" Square = (%f, %f)\n", s->x, s->y));
|
||||
write(sprintf(" Circle = (%f, %f)\n", c->x_get(), c->y_get()));
|
||||
write(sprintf(" Square = (%f, %f)\n", s->x_get(), s->y_get()));
|
||||
write(" Circle = (%f, %f)\n", c->x_get(), c->y_get());
|
||||
write(" Square = (%f, %f)\n", s->x_get(), s->y_get());
|
||||
|
||||
// ----- Call some methods -----
|
||||
|
||||
write("\nHere are some properties of the shapes:\n");
|
||||
write(" The circle:\n");
|
||||
write(sprintf(" area = %f.\n", c->area()));
|
||||
write(sprintf(" perimeter = %f.\n", c->perimeter()));
|
||||
// write(" " + (string) s + ".\n");
|
||||
write(" area = %f.\n", c->area());
|
||||
write(" perimeter = %f.\n", c->perimeter());
|
||||
write(" The square:\n");
|
||||
write(sprintf(" area = %f.\n", s->area()));
|
||||
write(sprintf(" perimeter = %f.\n", s->perimeter()));
|
||||
write(" area = %f.\n", s->area());
|
||||
write(" perimeter = %f.\n", s->perimeter());
|
||||
|
||||
write("\nGuess I'll clean up now\n");
|
||||
|
||||
// Note: this invokes the virtual destructor
|
||||
// del c;
|
||||
// del s;
|
||||
|
||||
// s = 3;
|
||||
// write(sprintf("%d shapes remain\n", Shape->nshapes));
|
||||
/* See if we can force 's' to be garbage-collected */
|
||||
s = 0;
|
||||
|
||||
/* Now we should be down to only 1 shape */
|
||||
write("%d shapes remain\n", Shape_nshapes_get());
|
||||
|
||||
/* Done */
|
||||
write("Goodbye\n");
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,13 @@
|
|||
* struct svalue), we're just calling the appropriate push_XXX
|
||||
* (e.g. push_int) to push the return value onto the stack.
|
||||
*
|
||||
* - Pike classes can't have static member functions or data, so we need
|
||||
* to find some other appropriate mapping for C++ static member functions
|
||||
* and data.
|
||||
*
|
||||
* - Pike doesn't seem to provide any default way to print the memory
|
||||
* address, etc. for extension objects. Should we do something here?
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
char cvsroot_pike_cxx[] = "$Header$";
|
||||
|
|
@ -32,6 +39,8 @@ private:
|
|||
File *f_header;
|
||||
File *f_wrappers;
|
||||
File *f_init;
|
||||
File *f_classInit;
|
||||
|
||||
String *PrefixPlusUnderscore;
|
||||
int current;
|
||||
|
||||
|
|
@ -60,6 +69,7 @@ public:
|
|||
f_header = 0;
|
||||
f_wrappers = 0;
|
||||
f_init = 0;
|
||||
f_classInit = 0;
|
||||
PrefixPlusUnderscore = 0;
|
||||
current = NO_CPP;
|
||||
}
|
||||
|
|
@ -118,6 +128,7 @@ public:
|
|||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
f_init = NewString("");
|
||||
f_classInit = NewString("");
|
||||
f_header = NewString("");
|
||||
f_wrappers = NewString("");
|
||||
|
||||
|
|
@ -126,6 +137,7 @@ public:
|
|||
Swig_register_filebyname("wrapper", f_wrappers);
|
||||
Swig_register_filebyname("runtime", f_runtime);
|
||||
Swig_register_filebyname("init", f_init);
|
||||
Swig_register_filebyname("classInit", f_classInit);
|
||||
|
||||
/* Standard stuff for the SWIG runtime section */
|
||||
Swig_banner(f_runtime);
|
||||
|
|
@ -154,9 +166,12 @@ public:
|
|||
Dump(f_header, f_runtime);
|
||||
Dump(f_wrappers, f_runtime);
|
||||
Wrapper_pretty_print(f_init, f_runtime);
|
||||
|
||||
Delete(f_header);
|
||||
Delete(f_wrappers);
|
||||
Delete(f_init);
|
||||
Delete(f_classInit);
|
||||
|
||||
Close(f_runtime);
|
||||
Delete(f_runtime);
|
||||
|
||||
|
|
@ -221,12 +236,28 @@ public:
|
|||
|
||||
void add_method(Node *n, const DOHString_or_char *name, const DOHString_or_char *function, const DOHString_or_char *description) {
|
||||
String *rename;
|
||||
if (current != NO_CPP) {
|
||||
rename = strip(name);
|
||||
} else {
|
||||
rename = NewString(name);
|
||||
switch (current) {
|
||||
case NO_CPP:
|
||||
rename = NewString(name);
|
||||
Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
|
||||
break;
|
||||
case STATIC_FUNC:
|
||||
case STATIC_VAR:
|
||||
rename = NewString(name);
|
||||
Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
|
||||
break;
|
||||
case CONSTRUCTOR:
|
||||
case DESTRUCTOR:
|
||||
case MEMBER_FUNC:
|
||||
case MEMBER_VAR:
|
||||
rename = strip(name);
|
||||
Printf(f_classInit, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
|
||||
break;
|
||||
case CLASS_CONST:
|
||||
assert(false); // shouldn't have gotten here for CLASS_CONST nodes
|
||||
default:
|
||||
assert(false); // what is this?
|
||||
}
|
||||
Printf(f_init, "ADD_FUNCTION(\"%s\", %s, tFunc(%s), 0);\n", rename, function, description);
|
||||
Delete(rename);
|
||||
}
|
||||
|
||||
|
|
@ -606,7 +637,7 @@ public:
|
|||
|
||||
PrefixPlusUnderscore = NewStringf("%s_", getClassPrefix());
|
||||
|
||||
Printf(f_init, "start_new_program();\n");
|
||||
Printf(f_classInit, "start_new_program();\n");
|
||||
|
||||
/* Handle inheritance */
|
||||
List *baselist = Getattr(n,"bases");
|
||||
|
|
@ -621,13 +652,13 @@ public:
|
|||
SwigType_add_pointer(basetype);
|
||||
SwigType_remember(basetype);
|
||||
String *basemangle = SwigType_manglestr(basetype);
|
||||
Printf(f_init, "low_inherit((struct program *) SWIGTYPE%s->clientdata, 0, 0, 0, 0, 0);\n", basemangle);
|
||||
Printf(f_classInit, "low_inherit((struct program *) SWIGTYPE%s->clientdata, 0, 0, 0, 0, 0);\n", basemangle);
|
||||
Delete(basemangle);
|
||||
Delete(basetype);
|
||||
base = Nextitem(baselist);
|
||||
}
|
||||
} else {
|
||||
Printf(f_init, "ADD_STORAGE(swig_object_wrapper);\n");
|
||||
Printf(f_classInit, "ADD_STORAGE(swig_object_wrapper);\n");
|
||||
}
|
||||
|
||||
Language::classHandler(n);
|
||||
|
|
@ -640,8 +671,10 @@ public:
|
|||
}
|
||||
*/
|
||||
|
||||
/* Done, close the class */
|
||||
Printf(f_init, "add_program_constant(\"%s\", pr = end_program(), 0);\n", symname);
|
||||
/* Done, close the class and dump its definition to the init function */
|
||||
Printf(f_classInit, "add_program_constant(\"%s\", pr = end_program(), 0);\n", symname);
|
||||
Dump(f_classInit, f_init);
|
||||
Clear(f_classInit);
|
||||
|
||||
SwigType *tt = NewString(symname);
|
||||
SwigType_add_pointer(tt);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue