Miklos Vajna 2009-07-22 11:08:29 +00:00
commit 0249eea389
53 changed files with 2838 additions and 66 deletions

View file

@ -0,0 +1,22 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile php_clean
rm -f $(TARGET).php
check: all
$(MAKE) -f $(TOP)/Makefile php_run

View file

@ -0,0 +1,4 @@
/* File : example.cxx */
#include "example.h"

View file

@ -0,0 +1,22 @@
/* File : example.h */
#include <iostream>
class Callback {
public:
virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; }
virtual void run() { std::cout << "Callback::run()" << std::endl; }
};
class Caller {
private:
Callback *_callback;
public:
Caller(): _callback(0) {}
~Caller() { delCallback(); }
void delCallback() { delete _callback; _callback = 0; }
void setCallback(Callback *cb) { delCallback(); _callback = cb; }
void call() { if (_callback) _callback->run(); }
};

View file

@ -0,0 +1,13 @@
/* File : example.i */
%module(directors="1") example
%{
#include "example.h"
%}
%include "std_string.i"
/* turn on director wrapping Callback */
%feature("director") Callback;
%include "example.h"

View file

@ -0,0 +1,19 @@
<html>
<head>
<title>SWIG:Examples:php:callback</title>
</head>
<body bgcolor="#ffffff">
<tt>SWIG/Examples/php/callback/</tt>
<hr>
<H2>Implementing C++ callbacks in PHP</H2>
<p>
This example illustrates how to use directors to implement C++ callbacks in PHP.
<hr>
</body>
</html>

View file

@ -0,0 +1,47 @@
<?php
# This file illustrates the cross language polymorphism using directors.
require("example.php");
# Class, which overwrites Callback::run().
class PhpCallback extends Callback {
function run() {
print "PhpCallback.run()\n";
}
};
# Create an Caller instance
$caller = new Caller();
# Add a simple C++ callback (caller owns the callback, so
# we disown it first by clearing the .thisown flag).
print "Adding and calling a normal C++ callback\n";
print "----------------------------------------\n";
$callback = new Callback();
$callback->thisown = 0;
$caller->setCallback($callback);
$caller->call();
$caller->delCallback();
print "\n";
print "Adding and calling a PHP callback\n";
print "------------------------------------\n";
# Add a PHP callback.
$callback = new PhpCallback();
$callback->thisown = 0;
$caller->setCallback($callback);
$caller->call();
$caller->delCallback();
# All done.
print "php exit\n";
?>

View file

@ -0,0 +1,22 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myphp' INTERFACE='$(INTERFACE)' php_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile php_clean
rm -f $(TARGET).php
check: all
$(MAKE) -f $(TOP)/Makefile php_run

View file

@ -0,0 +1,4 @@
/* File : example.cxx */
#include "example.h"

View 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 *get_item(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;
}
};

View file

@ -0,0 +1,15 @@
/* File : example.i */
%module(directors="1") example
%{
#include "example.h"
%}
%include "std_vector.i"
%include "std_string.i"
/* turn on director wrapping for Manager */
%feature("director") Employee;
%feature("director") Manager;
%include "example.h"

View file

@ -0,0 +1,19 @@
<html>
<head>
<title>SWIG:Examples:php:extend</title>
</head>
<body bgcolor="#ffffff">
<tt>SWIG/Examples/php/extend/</tt>
<hr>
<H2>Extending a simple C++ class in PHP</H2>
<p>
This example illustrates the extending of a C++ class with cross language polymorphism.
<hr>
</body>
</html>

View file

@ -0,0 +1,76 @@
<?php
# This file illustrates the cross language polymorphism using directors.
require("example.php");
# CEO class, which overrides Employee::getPosition().
class CEO extends Manager {
function getPosition() {
return "CEO";
}
}
# Create an instance of our employee extension class, CEO. The calls to
# getName() and getPosition() are standard, the call to getTitle() uses
# the director wrappers to call CEO.getPosition.
$e = new CEO("Alice");
print $e->getName() . " is a " . $e->getPosition() . "\n";
printf("Just call her \"%s\"\n", $e->getTitle());
print "----------------------\n";
# Create a new EmployeeList instance. This class does not have a C++
# director wrapper, but can be used freely with other classes that do.
$list = new EmployeeList();
# EmployeeList owns its items, so we must surrender ownership of objects
# we add. This involves first clearing the ->disown member to tell the
# C++ director to start reference counting.
$e->thisown = 0;
$list->addEmployee($e);
print "----------------------\n";
# 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, both all methods resolve in C++. For item 3, our CEO, getTitle calls
# getPosition which resolves in PHP. The call to getPosition is
# slightly different, however, from the e.getPosition() call above, since
# now the object reference has been "laundered" by passing through
# EmployeeList as an Employee*. Previously, PHP resolved the call
# immediately in CEO, but now PHP thinks the object is an instance of
# class Employee (actually EmployeePtr). So the call passes through the
# Employee proxy class and on to the C wrappers and C++ director,
# eventually ending up back at the 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 PHP implementation
# in CEO. All this routing takes place transparently.
print "(position, title) for items 0-3:\n";
printf(" %s, \"%s\"\n", $list->get_item(0)->getPosition(), $list->get_item(0)->getTitle());
printf(" %s, \"%s\"\n", $list->get_item(1)->getPosition(), $list->get_item(1)->getTitle());
printf(" %s, \"%s\"\n", $list->get_item(2)->getPosition(), $list->get_item(2)->getTitle());
printf(" %s, \"%s\"\n", $list->get_item(3)->getPosition(), $list->get_item(3)->getTitle());
print "----------------------\n";
# Time to delete the EmployeeList, which will delete all the Employee*
# items it contains. The last item is our CEO, which gets destroyed as its
# reference count goes to zero. The PHP destructor runs, and is still
# able to call the getName() method since the underlying C++ object still
# exists. After this destructor runs the remaining C++ destructors run as
# usual to destroy the object.
unset($list);
print "----------------------\n";
# All done.
print "php exit\n";
?>

View file

@ -1,6 +1,5 @@
/* File : example.h */
#include <cstdio>
#include <iostream>
class Callback {

View file

@ -15,7 +15,9 @@
%feature("director") Foo;
%newobject Foo::cloner();
%newobject Foo::get_class();
%newobject Bar::cloner();
%newobject Bar::get_class();
%inline {

View file

@ -11,6 +11,13 @@
%newobject *::create();
#ifdef SWIGPHP
// TODO: Currently we do not track the dynamic type of returned objects
// in PHP, so we need the factory helper.
%include factory.i
%factory(Foo *Bar::create, Bar);
#endif
%rename(a) Bar::hello;
%rename(s) Foo::p;
%rename(q) Foo::r;

View file

@ -17,7 +17,11 @@
%feature("director") Foo;
%feature("director:except") {
#ifndef SWIGPHP
if ($error != NULL) {
#else
if ($error == FAILURE) {
#endif
throw Swig::DirectorMethodException();
}
}

View file

@ -6,6 +6,9 @@
%newobject Geometry::clone;
%factory(Geometry *Geometry::create, Point, Circle);
%factory(Geometry *Geometry::clone, Point, Circle);
#ifdef SWIGPHP
%rename(clone_) clone;
#endif
%factory(Geometry *Point::clone, Point, Circle);
%factory(Geometry *Circle::clone, Point, Circle);

View file

@ -17,7 +17,7 @@ include $(srcdir)/../common.mk
TARGETPREFIX =# Should be php_ for Windows, empty otherwise
# Custom tests - tests with additional commandline options
# none!
prefix.cpptest: SWIGOPT += -prefix Project
# write out tests without a _runme.php
missingcpptests:

View file

@ -0,0 +1,62 @@
<?php
require "tests.php";
require "director_abstract.php";
// No new functions
check::functions(array(foo_ping,foo_pong,example0_getxsize,example0_color,example0_get_color,example1_getxsize,example1_color,example1_get_color,example2_getxsize,example2_color,example2_get_color,example4_getxsize,example4_color,example4_get_color,example3_i_color,example3_i_get_color,g,a_f));
// No new classes
check::classes(array(director_abstract,Foo,Example0,Example1,Example2,Example4,Example3_i,A));
// now new vars
check::globals(array());
class MyFoo extends Foo {
function ping() {
return "MyFoo::ping()";
}
}
$a = new MyFoo();
check::equal($a->ping(), "MyFoo::ping()", "MyFoo::ping failed");
check::equal($a->pong(), "Foo::pong();MyFoo::ping()", "MyFoo::pong failed");
class MyExample1 extends Example1 {
function Color($r, $g, $b) {
return $r;
}
}
class MyExample2 extends Example1 {
function Color($r, $g, $b) {
return $g;
}
}
class MyExample3 extends Example1 {
function Color($r, $g, $b) {
return $b;
}
}
$me1 = new MyExample1();
check::equal($me1->Color(1, 2, 3), 1, "Example1_get_color failed");
$me2 = new MyExample2(1, 2);
check::equal($me2->Color(1, 2, 3), 2, "Example2_get_color failed");
$me3 = new MyExample3();
check::equal($me3->Color(1, 2, 3), 3, "Example3_get_color failed");
$class = new ReflectionClass('Example1');
check::equal($class->isAbstract(), true, "Example1 abstractness failed");
$class = new ReflectionClass('Example2');
check::equal($class->isAbstract(), true, "Example2 abstractness failed");
$class = new ReflectionClass('Example3_i');
check::equal($class->isAbstract(), true, "Example3_i abstractness failed");
check::done();
?>

View file

@ -0,0 +1,58 @@
<?php
require "tests.php";
require "director_basic.php";
// No new functions
check::functions(array(foo_ping,foo_pong,foo_get_self,a_f,a_rg,a1_ff,myclass_method,myclass_vmethod,myclass_pmethod,myclass_cmethod,myclass_get_self,myclass_call_pmethod,myclasst_i_method));
// No new classes
check::classes(array(Foo,A,A1,Bar,MyClass,MyClassT_i));
// now new vars
check::globals(array(bar_x));
class PhpFoo extends Foo {
function ping() {
return "PhpFoo::ping()";
}
}
$a = new PhpFoo();
check::equal($a->ping(), "PhpFoo::ping()", "ping failed");
check::equal($a->pong(), "Foo::pong();PhpFoo::ping()", "pong failed");
$b = new Foo();
check::equal($b->ping(), "Foo::ping()", "ping failed");
check::equal($b->pong(), "Foo::pong();Foo::ping()", "pong failed");
$a = new A1(1);
check::equal($a->rg(2), 2, "rg failed");
class PhpClass extends MyClass {
function vmethod($b) {
$b->x = $b->x + 31;
return $b;
}
}
$b = new Bar(3);
$d = new MyClass();
$c = new PhpClass();
$cc = MyClass::get_self($c);
$dd = MyClass::get_self($d);
$bc = $cc->cmethod($b);
$bd = $dd->cmethod($b);
$cc->method($b);
check::equal($bc->x, 34, "bc failed");
check::equal($bd->x, 16, "bd failed");
check::done();
?>

View file

@ -0,0 +1,150 @@
<?php
require "tests.php";
require "director_classic.php";
// No new functions
check::functions(array(being_id,person_id,child_id,grandchild_id,caller_delcallback,caller_setcallback,caller_resetcallback,caller_call,caller_baseclass));
// No new classes
check::classes(array(Being,Person,Child,GrandChild,OrphanPerson,OrphanChild,Caller));
// now new vars
check::globals(array());
class TargetLangPerson extends Person {
function id() {
$identifier = "TargetLangPerson";
return $identifier;
}
}
class TargetLangChild extends Child {
function id() {
$identifier = "TargetLangChild";
return $identifier;
}
}
class TargetLangGrandChild extends GrandChild {
function id() {
$identifier = "TargetLangGrandChild";
return $identifier;
}
}
# Semis - don't override id() in target language
class TargetLangSemiPerson extends Person {
# No id() override
}
class TargetLangSemiChild extends Child {
# No id() override
}
class TargetLangSemiGrandChild extends GrandChild {
# No id() override
}
# Orphans - don't override id() in C++
class TargetLangOrphanPerson extends OrphanPerson {
function id() {
$identifier = "TargetLangOrphanPerson";
return $identifier;
}
}
class TargetLangOrphanChild extends OrphanChild {
function id() {
$identifier = "TargetLangOrphanChild";
return $identifier;
}
}
function mycheck($person, $expected) {
$debug = 0;
# Normal target language polymorphic call
$ret = $person->id();
if ($debug)
print $ret . "\n";
check::equal($ret, $expected, "#1 failed");
# Polymorphic call from C++
$caller = new Caller();
$caller->setCallback($person);
$ret = $caller->call();
if ($debug)
print $ret . "\n";
check::equal($ret, $expected, "#2 failed");
# Polymorphic call of object created in target language and passed to
# C++ and back again
$baseclass = $caller->baseClass();
$ret = $baseclass->id();
if ($debug)
print $ret . "\n";
# TODO: Currently we do not track the dynamic type of returned
# objects, so in case it's possible that the dynamic type is not equal
# to the static type, we skip this check.
if (get_parent_class($person) === false)
check::equal($ret, $expected, "#3 failed");
$caller->resetCallback();
if ($debug)
print "----------------------------------------\n";
}
$person = new Person();
mycheck($person, "Person");
unset($person);
$person = new Child();
mycheck($person, "Child");
unset($person);
$person = new GrandChild();
mycheck($person, "GrandChild");
unset($person);
$person = new TargetLangPerson();
mycheck($person, "TargetLangPerson");
unset($person);
$person = new TargetLangChild();
mycheck($person, "TargetLangChild");
unset($person);
$person = new TargetLangGrandChild();
mycheck($person, "TargetLangGrandChild");
unset($person);
# Semis - don't override id() in target language
$person = new TargetLangSemiPerson();
mycheck($person, "Person");
unset($person);
$person = new TargetLangSemiChild();
mycheck($person, "Child");
unset($person);
$person = new TargetLangSemiGrandChild();
mycheck($person, "GrandChild");
unset($person);
# Orphans - don't override id() in C++
$person = new OrphanPerson();
mycheck($person, "Person");
unset($person);
$person = new OrphanChild();
mycheck($person, "Child");
unset($person);
$person = new TargetLangOrphanPerson();
mycheck($person, "TargetLangOrphanPerson");
unset($person);
$person = new TargetLangOrphanChild();
mycheck($person, "TargetLangOrphanChild");
unset($person);
check::done();
?>

View file

@ -0,0 +1,20 @@
<?php
require "tests.php";
require "director_default.php";
// No new functions
check::functions(array(foo_msg,foo_getmsg,bar_msg,bar_getmsg,defaultsbase_defaultargs,defaultsderived_defaultargs));
// No new classes
check::classes(array(Foo,Bar,DefaultsBase,DefaultsDerived));
// now new vars
check::globals(array());
$f = new Foo();
$f = new Foo(1);
$f = new Bar();
$f = new Bar(1);
check::done();
?>

View file

@ -0,0 +1,55 @@
<?php
require "tests.php";
require "director_detect.php";
// No new functions
check::functions(array(foo_cloner,foo_get_value,foo_get_class,foo_just_do_it,bar_baseclass,bar_cloner,bar_get_value,bar_get_class,bar_just_do_it));
// No new classes
check::classes(array(A,Foo,Bar));
// now new vars
check::globals(array());
class MyBar extends Bar {
function __construct($val = 2) {
parent::__construct();
$this->val = $val;
}
function get_value() {
$this->val = $this->val + 1;
return $this->val;
}
function get_class() {
$this->val = $this->val + 1;
return new A();
}
function just_do_it() {
$this->val = $this->val + 1;
}
/* clone is a reserved keyword */
function clone_() {
return new MyBar($this->val);
}
}
$b = new MyBar();
$f = $b->baseclass();
$v = $f->get_value();
$a = $f->get_class();
$f->just_do_it();
$c = $b->clone_();
$vc = $c->get_value();
check::equal($v, 3, "f: Bad virtual detection");
check::equal($b->val, 5, "b: Bad virtual detection");
check::equal($vc, 6, "c: Bad virtual detection");
check::done();
?>

View file

@ -0,0 +1,25 @@
<?php
require "tests.php";
require "director_enum.php";
// No new functions
check::functions(array(foo_say_hello,foo_say_hi,foo_say_bye,foo_say_hi_ref,foo_ping,foo_ping_ref,foo_ping_member_enum,a_f,a2_f));
// No new classes
check::classes(array(director_enum,Foo,A,B,A2,B2));
// now new vars
check::globals(array());
class MyFoo extends Foo {
function say_hi($val) {
return $val;
}
}
$b = new Foo();
$a = new MyFoo();
check::equal($a->say_hi(director_enum::hello), $b->say_hello(director_enum::hi), "say failed");
check::done();
?>

View file

@ -0,0 +1,78 @@
<?php
require "tests.php";
require "director_exception.php";
// No new functions
check::functions(array(foo_ping,foo_pong,launder,bar_ping,bar_pong,bar_pang));
// No new classes
check::classes(array(director_exception,Foo,Exception1,Exception2,Base,Bar));
// now new vars
check::globals(array());
class MyException extends Exception {
function __construct($a, $b) {
$this->msg = $a . $b;
}
}
class MyFoo extends Foo {
function ping() {
throw new Exception("MyFoo::ping() EXCEPTION");
}
}
class MyFoo2 extends Foo {
function ping() {
return true;
}
}
class MyFoo3 extends Foo {
function ping() {
throw new MyException("foo", "bar");
}
}
# Check that the Exception raised by MyFoo.ping() is returned by
# MyFoo.pong().
$ok = 0;
$a = new MyFoo();
# TODO: Currently we do not track the dynamic type of returned
# objects, so we skip the launder() call.
#$b = director_exception::launder($a);
$b = $a;
try {
$b->pong();
} catch (Exception $e) {
$ok = 1;
check::equal($e->getMessage(), "MyFoo::ping() EXCEPTION", "Unexpected error message #1");
}
check::equal($ok, 1, "Got no exception while expected one #1");
# Check that the director can return an exception which requires two
# arguments to the constructor, without mangling it.
$ok = 0;
$a = new MyFoo3();
#$b = director_exception::launder($a);
$b = $a;
try {
$b->pong();
} catch (Exception $e) {
$ok = 1;
check::equal($e->msg, "foobar", "Unexpected error message #2");
}
check::equal($ok, 1, "Got no exception while expected one #2");
try {
throw new Exception2();
} catch (Exception2 $e2) {
}
try {
throw new Exception1();
} catch (Exception1 $e1) {
}
check::done();
?>

View file

@ -0,0 +1,29 @@
<?php
require "tests.php";
require "director_extend.php";
// No new functions
check::functions(array(spobject_getfoobar,spobject_dummy,spobject_exceptionmethod));
// No new classes
check::classes(array(SpObject));
// now new vars
check::globals(array());
class MyObject extends SpObject{
function __construct() {
parent::__construct();
return;
}
function getFoo() {
return 123;
}
}
$m = new MyObject();
check::equal($m->dummy(), 666, "1st call");
check::equal($m->dummy(), 666, "2st call"); // Locked system
check::done();
?>

View file

@ -0,0 +1,61 @@
<?php
require "tests.php";
require "director_finalizer.php";
// No new functions
check::functions(array(foo_orstatus,deletefoo,getstatus,launder,resetstatus));
// No new classes
check::classes(array(director_finalizer,Foo));
// now new vars
check::globals(array());
class MyFoo extends Foo {
function __destruct() {
$this->orStatus(2);
if (method_exists(parent, "__destruct")) {
parent::__destruct();
}
}
}
resetStatus();
$a = new MyFoo();
unset($a);
check::equal(getStatus(), 3, "getStatus() failed #1");
resetStatus();
$a = new MyFoo();
launder($a);
check::equal(getStatus(), 0, "getStatus() failed #2");
unset($a);
check::equal(getStatus(), 3, "getStatus() failed #3");
resetStatus();
$a = new MyFoo();
$a->thisown = 0;
deleteFoo($a);
unset($a);
check::equal(getStatus(), 3, "getStatus() failed #4");
resetStatus();
$a = new MyFoo();
$a->thisown = 0;
deleteFoo(launder($a));
unset($a);
check::equal(getStatus(), 3, "getStatus() failed #5");
resetStatus();
check::done();
?>

View file

@ -0,0 +1,19 @@
<?php
require "tests.php";
require "director_frob.php";
// No new functions
check::functions(array(alpha_abs_method,bravo_abs_method,charlie_abs_method,ops_opint,ops_opintstarstarconst,ops_opintamp,ops_opintstar,ops_opconstintintstar,prims_ull,prims_callull,corecallbacks_on3dengineredrawn,corecallbacks_on3dengineredrawn2));
// No new classes
check::classes(array(Alpha,Bravo,Charlie,Delta,Ops,Prims,corePoint3d,coreCallbacks_On3dEngineRedrawnData,coreCallbacksOn3dEngineRedrawnData,coreCallbacks));
// now new vars
check::globals(array(corecallbacks_on3dengineredrawndata__eye,corecallbacks_on3dengineredrawndata__at,corecallbackson3dengineredrawndata__eye,corecallbackson3dengineredrawndata__at));
$foo = new Bravo();
$s = $foo->abs_method();
check::equal($s, "Bravo::abs_method()", "s failed");
check::done();
?>

View file

@ -0,0 +1,75 @@
<?php
// Sample test file
require "tests.php";
require "director_nested.php";
// No new functions
check::functions(array(foo_int_advance,foo_int_do_advance,bar_step,bar_do_advance,bar_do_step,foobar_int_get_value,foobar_int_get_name,foobar_int_name,foobar_int_get_self,foobar_int_do_advance,foobar_int_do_step));
// No new classes
check::classes(array(Foo_int,Bar,FooBar_int));
// now new vars
check::globals(array());
class A extends FooBar_int {
function do_step() {
return "A::do_step;";
}
function get_value() {
return "A::get_value";
}
}
$a = new A();
check::equal($a->step(), "Bar::step;Foo::advance;Bar::do_advance;A::do_step;", "Bad A virtual resolution");
class B extends FooBar_int {
function do_advance() {
return "B::do_advance;" . $this->do_step();
}
function do_step() {
return "B::do_step;";
}
function get_value() {
return 1;
}
}
$b = new B();
check::equal($b->step(), "Bar::step;Foo::advance;B::do_advance;B::do_step;", "Bad B virtual resolution");
class C extends FooBar_int {
function do_advance() {
return "C::do_advance;" . parent::do_advance();
}
function do_step() {
return "C::do_step;";
}
function get_value() {
return 2;
}
function get_name() {
return parent::get_name() . " hello";
}
}
$cc = new C();
# TODO: Currently we do not track the dynamic type of returned
# objects, so we skip the get_self() call.
#$c = Foobar_int::get_self($cc);
$c = $cc;
$c->advance();
check::equal($c->get_name(), "FooBar::get_name hello", "get_name failed");
check::equal($c->name(), "FooBar::get_name hello", "name failed");
check::done();
?>

View file

@ -0,0 +1,53 @@
<?php
require "tests.php";
require "director_profile.php";
// No new functions
check::functions(array(b_fn,b_vfi,b_fi,b_fj,b_fk,b_fl,b_get_self,b_vfs,b_fs));
// No new classes
check::classes(array(A,B));
// now new vars
check::globals(array());
class MyB extends B {
function vfi($a) {
return $a+3;
}
}
$a = new A();
$myb = new MyB();
$b = B::get_self($myb);
$i = 50000;
$a = 1;
while ($i) {
$a = $b->fi($a); #1
$a = $b->fi($a); #2
$a = $b->fi($a); #3
$a = $b->fi($a); #4
$a = $b->fi($a); #5
$a = $b->fi($a); #6
$a = $b->fi($a); #7
$a = $b->fi($a); #8
$a = $b->fi($a); #9
$a = $b->fi($a); #10
$a = $b->fi($a); #1
$a = $b->fi($a); #2
$a = $b->fi($a); #3
$a = $b->fi($a); #4
$a = $b->fi($a); #5
$a = $b->fi($a); #6
$a = $b->fi($a); #7
$a = $b->fi($a); #8
$a = $b->fi($a); #9
$a = $b->fi($a); #20
$i -= 1;
}
print $a . "\n";
check::done();
?>

View file

@ -0,0 +1,54 @@
<?php
require "tests.php";
require "director_protected.php";
// No new functions
check::functions(array(foo_pong,foo_s,foo_q,foo_ping,foo_pang,foo_used,bar_create,bar_pong,bar_used,bar_ping,bar_pang,a_draw,b_draw));
// No new classes
check::classes(array(Foo,Bar,PrivateFoo,A,B,AA,BB));
// now new vars
check::globals(array(bar_a));
class FooBar extends Bar {
protected function ping() {
return "FooBar::ping();";
}
}
class FooBar2 extends Bar {
function ping() {
return "FooBar2::ping();";
}
function pang() {
return "FooBar2::pang();";
}
}
$b = new Bar();
$f = $b->create();
$fb = new FooBar();
$fb2 = new FooBar2();
check::equal($fb->used(), "Foo::pang();Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::used");
check::equal($fb2->used(), "FooBar2::pang();Bar::pong();Foo::pong();FooBar2::ping();", "bad FooBar2::used");
check::equal($b->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Bar::pong");
check::equal($f->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Foo::pong");
check::equal($fb->pong(), "Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::pong");
$method = new ReflectionMethod('Bar', 'ping');
check::equal($method->isProtected(), true, "Boo::ping should be protected");
$method = new ReflectionMethod('Foo', 'ping');
check::equal($method->isProtected(), true, "Foo::ping should be protected");
$method = new ReflectionMethod('FooBar', 'pang');
check::equal($method->isProtected(), true, "FooBar::pang should be protected");
check::done();
?>

View file

@ -0,0 +1,60 @@
<?php
require "tests.php";
require "director_stl.php";
// No new functions
check::functions(array(foo_bar,foo_ping,foo_pong,foo_tping,foo_tpong,foo_pident,foo_vident,foo_vsecond,foo_tpident,foo_tvident,foo_tvsecond,foo_vidents,foo_tvidents));
// No new classes
check::classes(array(Foo));
// now new vars
check::globals(array());
class MyFoo extends Foo {
function ping($s) {
return "MyFoo::ping():" . $s;
}
function pident($arg) {
return $arg;
}
function vident($v) {
return $v;
}
function vidents($v) {
return $v;
}
function vsecond($v1, $v2) {
return $v2;
}
}
$a = new MyFoo();
$a->tping("hello");
$a->tpong("hello");
# TODO: automatic conversion between PHP arrays and std::pair or
# std::vector is not yet implemented.
/*$p = array(1, 2);
$a->pident($p);
$v = array(3, 4);
$a->vident($v);
$a->tpident($p);
$a->tvident($v);
$v1 = array(3, 4);
$v2 = array(5, 6);
$a->tvsecond($v1, $v2);
$vs = array("hi", "hello");
$vs;
$a->tvidents($vs);*/
check::done();
?>

View file

@ -0,0 +1,34 @@
<?php
require "tests.php";
require "director_string.php";
// No new functions
check::functions(array(a_get_first,a_call_get_first,a_string_length,a_process_text,a_call_process_func,stringvector_size,stringvector_is_empty,stringvector_clear,stringvector_push,stringvector_pop));
// No new classes
check::classes(array(A,StringVector));
// now new vars
check::globals(array(a,a_call,a_m_strings,stringvector));
class B extends A {
function get_first() {
return parent::get_first() . " world!";
}
function process_text($string) {
parent::process_text($string);
$this->smem = "hello";
}
}
$b = new B("hello");
$b->get(0);
check::equal($b->get_first(),"hello world!", "get_first failed");
$b->call_process_func();
check::equal($b->smem, "hello", "smem failed");
check::done();
?>

View file

@ -0,0 +1,29 @@
<?php
require "tests.php";
require "director_thread.php";
// No new functions
check::functions(array(millisecondsleep,foo_stop,foo_run,foo_do_foo));
// No new classes
check::classes(array(director_thread,Foo));
// now new vars
check::globals(array(foo_val));
class Derived extends Foo {
function do_foo() {
$this->val = $this->val - 1;
}
}
$d = new Derived();
$d->run();
if ($d->val >= 0) {
check::fail($d->val);
}
$d->stop();
check::done();
?>

View file

@ -0,0 +1,29 @@
<?php
require "tests.php";
require "director_unroll.php";
// No new functions
check::functions(array(foo_ping,foo_pong));
// No new classes
check::classes(array(Foo,Bar));
// now new vars
check::globals(array(bar));
class MyFoo extends Foo {
function ping() {
return "MyFoo::ping()";
}
}
$a = new MyFoo();
$b = new Bar();
$b->set($a);
$c = $b->get();
check::equal($a->this, $c->this, "this failed");
check::done();
?>

View file

@ -31,7 +31,8 @@ $spam=new spam();
check::is_a($spam,"spam");
check::equal(1,$spam->_foo,"1==spam->_foo");
check::equal(2,$spam->_bar,"2==spam->_bar");
check::equal(3,$spam->_baz,"3==spam->_baz");
// multiple inheritance not supported in PHP
check::equal(null,$spam->_baz,"null==spam->_baz");
check::equal(4,$spam->_spam,"4==spam->_spam");
check::done();

View file

@ -11,5 +11,11 @@ check::classes(array(doubleArray));
// now new vars
check::globals(array());
$d = new doubleArray(10);
$d->setitem(0, 7);
$d->setitem(5, $d->getitem(0) + 3);
check::equal($d->getitem(0) + $d->getitem(5), 17., "7+10==17");
check::done();
?>

View file

@ -0,0 +1,22 @@
<?php
require "tests.php";
require "li_factory.php";
// No new functions
check::functions(array(geometry_draw,geometry_create,geometry_clone_,point_draw,point_width,point_clone_,circle_draw,circle_radius,circle_clone_));
// No new classes
check::classes(array(Geometry,Point,Circle));
// now new vars
check::globals(array());
$circle = Geometry::create(Geometry::CIRCLE);
$r = $circle->radius();
check::equal($r, 1.5, "r failed");
$point = Geometry::create(Geometry::POINT);
$w = $point->width();
check::equal($w, 1.0, "w failed");
check::done();
?>

View file

@ -0,0 +1,20 @@
<?php
// Sample test file
require "tests.php";
require "newobject1.php";
// No new functions
check::functions(array(foo_makefoo,foo_makemore,foo_foocount));
// No new classes
check::classes(array(Foo));
// now new vars
check::globals(array());
$foo = Foo::makeFoo();
check::equal(get_class($foo), "Foo", "static failed");
$bar = $foo->makeMore();
check::equal(get_class($bar), "Foo", "regular failed");
check::done();
?>

View file

@ -0,0 +1,19 @@
<?php
// Sample test file
require "tests.php";
require "prefix.php";
// No new functions
check::functions(array(foo_get_self));
// No new classes
check::classes(array(ProjectFoo));
// now new vars
check::globals(array());
$f = new ProjectFoo();
// This resulted in "Fatal error: Class 'Foo' not found"
$f->get_self();
check::done();
?>

View file

@ -34,8 +34,11 @@ class check {
$df=array_flip($df[internal]);
foreach($_original_functions[internal] as $func) unset($df[$func]);
// Now chop out any get/set accessors
foreach(array_keys($df) as $func) if (GETSET && ereg('_[gs]et$',$func)) $extrags[]=$func;
else $extra[]=$func;
foreach(array_keys($df) as $func)
if ((GETSET && ereg('_[gs]et$',$func)) || ereg('^new_', $func)
|| ereg('_(alter|get)_newobject$', $func))
$extrags[]=$func;
else $extra[]=$func;
// $extra=array_keys($df);
}
if ($gs) return $extrags;

View file

@ -0,0 +1,14 @@
// Test that was failing for PHP - the value of the -prefix option was
// ignored
%module prefix
%inline %{
class Foo {
public:
Foo *get_self() {
return this;
}
};
%}