Проблема с использованием DOTNET с PHP.

Я пытался вызвать сборку .net с PHP через com (используя DOTNET ()). Похоже, что php находит DLL и правильно инициализирует, но по какой-то причине я не вижу / использую методы. Кто-нибудь знает, как я могу это исправить?

Вот код php, который я использую для вызова класса .net. Когда я называю это, выдается «hello1 hello2». Когда я пытаюсь напрямую вызвать функцию, выполняя $ csclass-> ModelBuilder ("", ""), я получаю ошибку сервера 500, указывающую, что она не может найти эту функцию.

<?php echo "hello1"; try{ $csclass = new DOTNET("ModelBuilder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1208136d23b48dc5", "ModelBuilder.ModelBuilder2"); $class_methods = get_class_methods($csclass); foreach ($class_methods as $method_name) { echo "$method_name\n"; } } catch (Exception $e) { echo 'Caught exception: ', $e->getMessage(), "\n"; } echo "hello2"; ?> 

Вот класс в сборке, которую я пытаюсь вызвать (построенный с использованием .net 3.5, подписанный с сильным именем и зарегистрированный в gacutil):

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using OfficeOpenXml; using System.Runtime.InteropServices; namespace ModelBuilder { [ClassInterface(ClassInterfaceType.AutoDual)] [ComVisible(true)] public class ModelBuilder2 { [ComVisible(true)] public Boolean BuildModel(String outputFileLoc,String excelTemplateFile) { try { //do stuff return true; } catch (Exception e) { return false; } } } 

Функция get_class_methods() не будет работать с объектом класса Dotnet. Эта вещь является прокси-сервером, и она не ведет себя так, как это делает обычный php-объект.

Если вы действительно сосредоточены на перечислении методов объекта, вам необходимо изучить реализацию IDispatch на вашем объекте .NET. Если, однако, ваша главная цель – просто использовать объект .NET, и ваша попытка перечислить методы была лишь побочным усилием, чтобы диагностировать, почему это не работает, тогда у меня есть некоторые предложения для вас.

  1. вместо использования gacutil , подумайте, можете ли вы вставить нужную DLL в каталог php, где находится php.exe. Если php.exe находится в c:\php5\php.exe , скопируйте сборку в c:\php5 .

  2. Если следовать приведенному выше предложению, сборка .NET не обязательно должна быть сильно названа. Он должен быть сильно назван, если вы планируете его использовать. Как я уже сказал, вам не нужно использовать GAC, чтобы загрузить его с помощью php. Если вы скопируете сборку в директорию PHP, вы можете использовать не подписанную сборку.

  3. Для ранней разработки и исследования с этим используйте программу php.exe из командной строки, вместо того, чтобы использовать IIS для запуска php через веб-запрос. Это позволяет вам видеть сообщения об ошибках напрямую, а не беспокоиться о 500 ошибках из IIS.


пример

Предположим, что это код C #:

 using System; namespace Ionic { public class MathEx { System.Random rnd; public MathEx () { rnd = new System.Random(); } public int RandomEven() { return rnd.Next()*2; } } } 

Скомпилируйте его из командной строки следующим образом:

 c:\net3.5\csc.exe /t:library /out:Ionic.MathEx.dll MathEx.cs 

скопируйте сборку в каталог, в котором содержится php.exe:

 copy Ionic.MathEx.dll \php 1 file(s) copied. 

Тогда предположим, что у меня есть php-скрипт с именем mathex.php с этим содержимым:

 <?php $my_assembly = 'Ionic.MathEx'; // name of the dll without the .dll suffix $clz = new DOTNET($my_assembly, 'Ionic.MathEx'); for ($i=0; $i<5; $i++) { echo $i . " " . $clz->RandomEven() . "\n"; } ?> 

… и если я запускаю его из командной строки следующим образом:

 \php\php.exe mathex.php 

… тогда я получаю следующие результаты:

 0 -1083602762 1 1535669896 2 -86761710 3 -1204365564 4 459406052 

Нота Бене

Я попытался сделать это с помощью сборки, собранной с .NET 4.0, но это не сработало, сообщив мне сообщение об ошибке несоответствия среды выполнения .NET. Как это:

 Fatal error: Uncaught exception 'com_exception' with message 'Failed to instantiate .Net object [CreateInstance] [0x8013101b] ' in C:\dev\php\mathEx.php:6 Stack trace: #0 C:\dev\php\mathEx.php(6): dotnet->dotnet('Ionic.MathEx', 'Ionic.MathEx') #1 {main} thrown in C:\dev\php\mathEx.php on line 6 

0x8013101b указывает несоответствие времени выполнения – версия выполнения сборки не соответствует версии приложения, которое пытается загрузить сборку.

Из этого я заключаю, что php5 скомпилирован для поддержки .NET 2.0 (включая 3.0 и 3.5). Версия среды выполнения изменилась для .NET 4.0, поэтому сборки, которые вы компилируете с помощью компилятора .NET 4.0 (включая VS2010), не будут использоваться с php5.exe. Обходной путь заключается в компиляции с компилятором .NET 2.0 или 3.5 (VS2005, vs2008).