Added support for the D programming languge.
It is still a bit rough around some edges, particularly with regard to multi-threading and operator overloading, and there are some documentation bits missing, but it should be fine for basic use. The test-suite should build and run fine with the current versions of DMD, LDC and Tango (at least) on Linux x86_64 and Mac OS X 10.6. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12299 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
a355d2d46a
commit
03aefbc6e9
176 changed files with 16449 additions and 29 deletions
28
Examples/d/extend/Makefile
Normal file
28
Examples/d/extend/Makefile
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
ifeq (2,$(D_VERSION))
|
||||
WORKING_DIR = d2/
|
||||
else
|
||||
WORKING_DIR = d1/
|
||||
endif
|
||||
|
||||
TOP = ../../..
|
||||
SWIG = $(TOP)/../preinst-swig
|
||||
EXTRA_CFLAGS = -I../ ../example.cxx example_wrap.cxx
|
||||
EXTRA_LDFLAGS = example.o example_wrap.o
|
||||
TARGET = example_wrap
|
||||
SWIGOPT =
|
||||
DSRCS = *.d
|
||||
DFLAGS = -ofrunme
|
||||
|
||||
|
||||
all:: d
|
||||
|
||||
d::
|
||||
cd $(WORKING_DIR); \
|
||||
$(MAKE) -f $(TOP)/Makefile EXTRA_CFLAGS='$(EXTRA_CFLAGS)' EXTRA_LDFLAGS='$(EXTRA_LDFLAGS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT) -outcurrentdir ../example.i' TARGET='$(TARGET)' d_cpp; \
|
||||
$(MAKE) -f $(TOP)/Makefile DSRCS='$(DSRCS)' DFLAGS='$(DFLAGS)' d_compile
|
||||
|
||||
clean::
|
||||
cd $(WORKING_DIR); \
|
||||
$(MAKE) -f $(TOP)/Makefile d_clean
|
||||
|
||||
check: all
|
||||
75
Examples/d/extend/d1/runme.d
Normal file
75
Examples/d/extend/d1/runme.d
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/// This file illustrates the cross language polymorphism using directors.
|
||||
module runme;
|
||||
|
||||
import example;
|
||||
import tango.io.Stdout;
|
||||
|
||||
// CEO class, which overrides Employee.getPosition().
|
||||
class CEO : Manager {
|
||||
public:
|
||||
this( char[] name ) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
override char[] getPosition() {
|
||||
return "CEO";
|
||||
}
|
||||
|
||||
// Public method to stop the SWIG proxy base class from thinking it owns the underlying C++ memory.
|
||||
void disownMemory() {
|
||||
swigCMemOwn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Create an instance of CEO, a class derived from the D proxy of the
|
||||
// underlying C++ class. The calls to getName() and getPosition() are standard,
|
||||
// the call to getTitle() uses the director wrappers to call CEO.getPosition().
|
||||
|
||||
auto e = new CEO( "Alice" );
|
||||
Stdout.formatln( "{} is a {}.", e.getName(), e.getPosition() );
|
||||
Stdout.formatln( "Just call her '{}'.", e.getTitle() );
|
||||
Stdout( "----------------------" ).newline;
|
||||
|
||||
{
|
||||
// Create a new EmployeeList instance. This class does not have a C++
|
||||
// director wrapper, but can be used freely with other classes that do.
|
||||
scope auto list = new EmployeeList();
|
||||
|
||||
// EmployeeList owns its items, so we must surrender ownership of objects we add.
|
||||
e.disownMemory();
|
||||
list.addEmployee(e);
|
||||
Stdout( "----------------------" ).newline;
|
||||
|
||||
// Now we access the first four items in list (three are C++ objects that
|
||||
// EmployeeList's constructor adds, the last is our CEO). The virtual
|
||||
// methods of all these instances are treated the same. For items 0, 1, and
|
||||
// 2, all methods resolve in C++. For item 3, our CEO, getTitle calls
|
||||
// getPosition which resolves in D. The call to getPosition is
|
||||
// slightly different, however, because of the overidden getPosition() call, since
|
||||
// now the object reference has been "laundered" by passing through
|
||||
// EmployeeList as an Employee*. Previously, D resolved the call
|
||||
// immediately in CEO, but now D thinks the object is an instance of
|
||||
// class Employee. So the call passes through the
|
||||
// Employee proxy class and on to the C wrappers and C++ director,
|
||||
// eventually ending up back at the D CEO implementation of getPosition().
|
||||
// The call to getTitle() for item 3 runs the C++ Employee::getTitle()
|
||||
// method, which in turn calls getPosition(). This virtual method call
|
||||
// passes down through the C++ director class to the D implementation
|
||||
// in CEO. All this routing takes place transparently.
|
||||
|
||||
Stdout( "(position, title) for items 0-3:" ).newline;
|
||||
Stdout.formatln( " {}, '{}'", list.getItem(0).getPosition(), list.getItem(0).getTitle() );
|
||||
Stdout.formatln( " {}, '{}'", list.getItem(1).getPosition(), list.getItem(1).getTitle() );
|
||||
Stdout.formatln( " {}, '{}'", list.getItem(2).getPosition(), list.getItem(2).getTitle() );
|
||||
Stdout.formatln( " {}, '{}'", list.getItem(3).getPosition(), list.getItem(3).getTitle() );
|
||||
Stdout( "----------------------" ).newline;
|
||||
|
||||
// All Employees will be destroyed when the EmployeeList goes out of scope,
|
||||
// including the CEO instance.
|
||||
}
|
||||
Stdout( "----------------------" ).newline;
|
||||
|
||||
// All done.
|
||||
Stdout( "Exiting cleanly from D code." ).newline;
|
||||
}
|
||||
75
Examples/d/extend/d2/runme.d
Normal file
75
Examples/d/extend/d2/runme.d
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/// This file illustrates the cross language polymorphism using directors.
|
||||
module runme;
|
||||
|
||||
import std.stdio;
|
||||
import example;
|
||||
|
||||
// CEO class, which overrides Employee.getPosition().
|
||||
class CEO : Manager {
|
||||
public:
|
||||
this( string name ) {
|
||||
super( name );
|
||||
}
|
||||
|
||||
override string getPosition() const {
|
||||
return "CEO";
|
||||
}
|
||||
|
||||
// Public method to stop the SWIG proxy base class from thinking it owns the underlying C++ memory.
|
||||
void disownMemory() {
|
||||
swigCMemOwn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Create an instance of CEO, a class derived from the D proxy of the
|
||||
// underlying C++ class. The calls to getName() and getPosition() are standard,
|
||||
// the call to getTitle() uses the director wrappers to call CEO.getPosition().
|
||||
|
||||
auto e = new CEO( "Alice" );
|
||||
writefln( "%s is a %s.", e.getName(), e.getPosition() );
|
||||
writefln( "Just call her '%s'.", e.getTitle() );
|
||||
writeln( "----------------------" );
|
||||
|
||||
{
|
||||
// Create a new EmployeeList instance. This class does not have a C++
|
||||
// director wrapper, but can be used freely with other classes that do.
|
||||
scope auto list = new EmployeeList();
|
||||
|
||||
// EmployeeList owns its items, so we must surrender ownership of objects we add.
|
||||
e.disownMemory();
|
||||
list.addEmployee(e);
|
||||
writeln( "----------------------" );
|
||||
|
||||
// Now we access the first four items in list (three are C++ objects that
|
||||
// EmployeeList's constructor adds, the last is our CEO). The virtual
|
||||
// methods of all these instances are treated the same. For items 0, 1, and
|
||||
// 2, all methods resolve in C++. For item 3, our CEO, getTitle calls
|
||||
// getPosition which resolves in D. The call to getPosition is
|
||||
// slightly different, however, because of the overidden getPosition() call, since
|
||||
// now the object reference has been "laundered" by passing through
|
||||
// EmployeeList as an Employee*. Previously, D resolved the call
|
||||
// immediately in CEO, but now D thinks the object is an instance of
|
||||
// class Employee. So the call passes through the
|
||||
// Employee proxy class and on to the C wrappers and C++ director,
|
||||
// eventually ending up back at the D CEO implementation of getPosition().
|
||||
// The call to getTitle() for item 3 runs the C++ Employee::getTitle()
|
||||
// method, which in turn calls getPosition(). This virtual method call
|
||||
// passes down through the C++ director class to the D implementation
|
||||
// in CEO. All this routing takes place transparently.
|
||||
|
||||
writeln( "(position, title) for items 0-3:" );
|
||||
writefln( " %s, '%s'", list.getItem(0).getPosition(), list.getItem(0).getTitle() );
|
||||
writefln( " %s, '%s'", list.getItem(1).getPosition(), list.getItem(1).getTitle() );
|
||||
writefln( " %s, '%s'", list.getItem(2).getPosition(), list.getItem(2).getTitle() );
|
||||
writefln( " %s, '%s'", list.getItem(3).getPosition(), list.getItem(3).getTitle() );
|
||||
writeln( "----------------------" );
|
||||
|
||||
// All Employees will be destroyed when the EmployeeList goes out of scope,
|
||||
// including the CEO instance.
|
||||
}
|
||||
writeln( "----------------------" );
|
||||
|
||||
// All done.
|
||||
writeln( "Exiting cleanly from D code." );
|
||||
}
|
||||
4
Examples/d/extend/example.cxx
Normal file
4
Examples/d/extend/example.cxx
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/* File : example.cxx */
|
||||
|
||||
#include "example.h"
|
||||
|
||||
56
Examples/d/extend/example.h
Normal file
56
Examples/d/extend/example.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* File : example.h */
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
class Employee {
|
||||
private:
|
||||
std::string name;
|
||||
public:
|
||||
Employee(const char* n): name(n) {}
|
||||
virtual std::string getTitle() { return getPosition() + " " + getName(); }
|
||||
virtual std::string getName() { return name; }
|
||||
virtual std::string getPosition() const { return "Employee"; }
|
||||
virtual ~Employee() { printf("~Employee() @ %p\n", this); }
|
||||
};
|
||||
|
||||
|
||||
class Manager: public Employee {
|
||||
public:
|
||||
Manager(const char* n): Employee(n) {}
|
||||
virtual std::string getPosition() const { return "Manager"; }
|
||||
};
|
||||
|
||||
|
||||
class EmployeeList {
|
||||
std::vector<Employee*> list;
|
||||
public:
|
||||
EmployeeList() {
|
||||
list.push_back(new Employee("Bob"));
|
||||
list.push_back(new Employee("Jane"));
|
||||
list.push_back(new Manager("Ted"));
|
||||
}
|
||||
void addEmployee(Employee *p) {
|
||||
list.push_back(p);
|
||||
std::cout << "New employee added. Current employees are:" << std::endl;
|
||||
std::vector<Employee*>::iterator i;
|
||||
for (i=list.begin(); i!=list.end(); i++) {
|
||||
std::cout << " " << (*i)->getTitle() << std::endl;
|
||||
}
|
||||
}
|
||||
const Employee *getItem(int i) {
|
||||
return list[i];
|
||||
}
|
||||
~EmployeeList() {
|
||||
std::vector<Employee*>::iterator i;
|
||||
std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl;
|
||||
for (i=list.begin(); i!=list.end(); i++) {
|
||||
delete *i;
|
||||
}
|
||||
std::cout << "~EmployeeList empty." << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
14
Examples/d/extend/example.i
Normal file
14
Examples/d/extend/example.i
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* File : example.i */
|
||||
%module(directors="1") example
|
||||
%{
|
||||
#include "example.h"
|
||||
%}
|
||||
|
||||
%include "std_string.i"
|
||||
|
||||
/* turn on director wrapping for Manager */
|
||||
%feature("director") Employee;
|
||||
%feature("director") Manager;
|
||||
|
||||
%include "example.h"
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue