Проблемы с использованием DOTNET из PHP.
Я пытался вызвать сборку .net с PHP через com (используя DOTNET()). Похоже, php находит DLL и правильно инициализирует, но я по какой-то причине не могу видеть/использовать методы. Кто-нибудь знает, как я мог бы это исправить?
Вот php-код, который я использую для вызова класса .net. Когда я называю это, вывод "привет1 привет2". Когда я пытаюсь напрямую вызвать функцию, выполнив $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;
}
}
}
1 answers
get_class_methods()
не будет работать с объектом класса Dotnet. Эта штука является прокси-сервером, и она ведет себя не так, как обычный php-объект.
Если вы действительно сосредоточены на перечислении методов объекта, то вам нужно изучить возможность реализации IDispatch на вашем.ЧИСТЫЙ объект. Если, однако, ваша главная цель состоит в том, чтобы просто использовать .ЧИСТЫЙ объект, и ваша попытка перечислить методы была просто побочной попыткой диагностировать, почему это не работало, тогда у меня есть некоторые предложения для вас.
Вместо того, чтобы использовать
gacutil
, подумайте, можете ли вы вставить необходимую библиотеку DLL в каталог php, место, где php.exe проживает. Еслиphp.exe
находится вc:\php5\php.exe
, скопируйте свою сборку вc:\php5
.Если вы последуете приведенному выше предложению, то.СЕТЕВАЯ сборка не должна иметь строгого имени. Он должен быть строго назван, если вы планируете его GAC. Как я уже сказал, вам не нужно GAC, чтобы загрузить его с помощью php. Если вы скопируете сборка в директорию PHP, затем вы можете использовать неподписанную сборку.
Для ранней разработки и изучения этого используйте программу
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).