CLR vs. PHP types#
This article provides information on how the runtime treats .NET types. As a result, with respect to this specification, it is possible to pass values between .NET (assuming C#) and PHP code implicitly, without the need of marshalling or additional conversions.
Type System#
The following table shows compatible .NET types and the corresponding PHP type:
| .NET | PHP | PHP Features |
|---|---|---|
| PhpValue | mixed | |
| bool | boolean | |
| int, uint, long | integer | |
| double, float | double | |
| string, PhpString, byte[] | string | |
| object | object | -> |
| null | NULL | |
| PhpResource | resource | is_resource |
| PhpNumber | integer|double | |
| PhpArray, ArrayAccess, IList | array, ArrayAccess | [] |
| Iterator, IteratorAggregate, IEnumerable | iterable | foreach, is_iterable |
| delegate, IPhpCallable, string, PhpArray(2) | callable | call_user_func, is_callable, etc. |
| Nullable<T> | value|NULL | isset, unset |
System.Nullable<T>#
Values can be read from and assigned to the Nullable<T> type. Any value of type Nullable<T> is treated as its contained value or NULL. An automatic conversion is performed. The operator isset is using the Nullable.HasValue property implicitly.
class Test {
public int? Number; // nullable field
public double? Foo() { ... }; // return nullable from method
public void Bar(bool? b) { } // gets nullable parameter
}
<?php
$t = new Test;
$t->Number = 123; // assigns `new Nullable<int>(123)`
$t->Number = null; // assigns `default(Nullable<int>)`
isset( $t->Number ); // gets Number.HasValue
print_r( $t->Foo() ); // gets NULL or double
$t->Bar( NULL ); // passes `default(Nullable<bool>)` to the method
$t->Bar( true ); // passes `new Nullable<bool>(true)` to the method
System.Delegate#
PHP's concept of callables works with string pointing to a function name, array of two dimensions referring to a class and its method, classes with the __invoke method or instances of the Closure class. Variables of these types, denoted as callable, can be used for indirect calls as depicted in the sample below:
<?php
assert( is_callable($delegate) );
print_r( $delegate($arg1, $arg2) ); // $delegate is `callable`
PeachPie extends the set of callable types with any CLR delegate or objects implementing the IPhpCallable interface (Peachpie.Runtime.dll).
Sample C# code that passes a delegate to a PHP global variable:
mycontext.Globals["delegate"] = new Func<string, bool>( str => str.IsNormalized() );
System.Collections.IEnumerable#
The sample PHP code below is able to consume a variety of CLR objects in addition to PHP's array and Traversable.
<?php
foreach ($enumerable as $key => $value) { }
$enumerable may implement the following CLR interfaces:
IPhpEnumerable(Peachpie.Runtime.dll) is the extended version ofIEnumerable. Objects implementing this interface are capable of being enumerated in PHP'sforeach.IDictionary; objects implementing this interface.IEnumerable<(Key, Value)>; objects implementingIEnumerable<>ofValueTuplewith two items.IEnumerable<KeyValuePair<Key, Value>>; objects implementingIEnumerable<>ofKeyValuePair<,>.IEnumerablein general works withforeachas well.$keyis auto-incremented starting with0,$valueis the current value of the enumerator.
As a result, standard .NET classes such as .NET arrays, ArrayList, List<>, Dictionary<,> or enumerators created using C# yield are transparently supported by PHP's foreach construct.
foreach by reference#
<?php
foreach ($enumerable as $key => &$value) { $value = 0; }
PhpAlias from the enumerator. Otherwise an exception of type InvalidOperationException is thrown.
System.Collections.IList#
PHP allows the accessing of an array and objects implementing ArrayAccess with square brackets [] as shown in the example below:
<?php
echo $list[10];
PeachPie provides the feature for System.Collections.IList, which allows consuming .NET arrays, Lists and other classes in PHP.
C# Event#
Implemented in
1.2.0(#1141)
PeachPie runtime allows working with .NET/CLR event class members in order to register and unregister callables. The following code depicts a sample C# class and a sample PHP program adding and removing an anonymous function (or any PHP callable) to it.
class SampleContainer
{
public event EventHandler MyEvent;
}
<?php
$obj = new SampleContainer;
// add callable to the event handler:
$hook = $obj->MyEvent->add(
function ($sender, $arg) {
echo "hello!";
}
);
// remove callable from the event handler
$hook->close();
In PHP, the event class member is represented by an instance of a special class Pchp\Core\ClrEvent with the following method:
ClrEvent::add( callable $callback ): Pchp\Core\ClrEvent\Hook
The Pchp\Core\ClrEvent\Hook class methods:
Hook::close()Hook::dispose() // alias to close
C# Indexers#
PHP array operator [] can be used on objects implementing C# indexers.
The following example defines a C# indexer with sample get and set accessors.
using System;
class SampleIndexer
{
string[] arr = new string[100];
// Define the indexer to allow to use [] operator.
public string this[int i]
{
get { return arr[i]; }
set { arr[i] = value; }
}
}
The following PHP code makes use of the C# indexer implicitly.
<?php
$sample = new \SampleIndexer;
$sample[0] = "Hello";
echo $sample[0]; // prints "Hello"
The indexer implementation
#c# this[]is a syntactic sugar that results in compiler generated specialget_Itemandset_Itemmethods. PeachPie translates the array operator into the call to the correspondingget_Itemorset_Itemmethod.