麻烦使用PHP的DOTNET。 [英] Trouble using DOTNET from PHP.

查看:149
本文介绍了麻烦使用PHP的DOTNET。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图从PHP到com调用.net程序集(使用DOTNET())。好像php正在寻找DLL并正确初始化,但由于某种原因我无法看到/使用这些方法。有谁知道我怎么能解决这个问题?

I've been trying to call a .net assembly from PHP through com (using DOTNET()). It seems like php is finding the DLL and initializing properly, but I can't see/use the methods for some reason. Anyone know how I might be able to fix this?

这是我用来调用.net类的php代码。当我调用它时,输出是hello1 hello2。当我尝试通过执行$ csclass-> ModelBuilder(,)直接调用该函数时,我收到500服务器错误,指出它无法找到该函数。

Here is the php code I'm using to call the .net class. When I call it the output is "hello1 hello2". When I try to directly call the function by doing $csclass->ModelBuilder("","") I get a 500 server error specifying that it couldn't find the function.

<?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注册):

Here is the the class in the assembly I'm trying to call (built using .net 3.5, signed with a strong name, and registered with 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对象不同。

The get_class_methods() will not work with a Dotnet class object. That thing is a proxy, and it does not behave the way a normal php object does.

如果你真的专注于列出对象的方法,那么你需要研究在.NET对象上实现IDispatch。但是,如果您的主要目标是简单地使用 .NET对象,那么您尝试列出这些方法只是为了诊断 无法正常工作的原因,那我给你一些建议。

If you really are focused on listing the methods of the object, then you need to look into implementing IDispatch on your .NET object. If, however, your main goal is to simply use the .NET object, and your attempt to list the methods was just a side effort to diagnose why that was not working, then I have some suggestions for you.


  1. 而不是使用 gacutil ,考虑是否可以插入所需的DLL进入php目录,php.exe所在的位置。如果 php.exe 位于 c:\ php5 \\\ php.exe ,那么
    复制你的汇编到 c:\ php5

  1. rather than using gacutil, consider whether you can insert the required DLL into the php directory, the place where php.exe resides. If php.exe resides at c:\php5\php.exe, then copy your assembly into c:\php5.

如果您遵循上述建议,则无需强烈命名.NET程序集。如果您计划GAC,则需要强烈命名。正如我所说,你不需要GAC它,以便用PHP加载它。如果将程序集复制到PHP目录中,则可以使用未签名的程序集。

If you follow the above suggestion, the .NET assembly need not be strongly named. It needs to be strongly named if you plan to GAC it. As I said, you don't need to GAC it, in order to load it with php. If you copy the assembly into the PHP dir, then you can use an un-signed assembly.

对于早期开发和探索,请使用命令行中的 php.exe 程序而不是使用IIS通过Web请求启动PHP。这使您可以直接查看错误消息,而不必担心IIS中的500个错误。

For early development and exploration with this, use the php.exe program from the command-line, rather than using IIS to launch php via a web request. This lets you see the error messages directly, rather than worrying about 500 errors from IIS.






示例



假设这是C#代码:


Example

Suppose this is the C# code:

using System;
namespace Ionic
{
    public class MathEx
    {
        System.Random rnd;
        public MathEx ()
        {
            rnd = new System.Random();
        }

        public int RandomEven()
        {
            return rnd.Next()*2;
        }
    }
}

从命令编译 - 像这样的行:

Compile it from the command-line like this:

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

将程序集复制到保存php.exe的目录:

copy the assembly to the dir that holds php.exe:

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

然后,假设我有一个名为mathex.php的php脚本,其中包含以下内容:

Then, suppose I have a php script named mathex.php with these contents:

<?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";
}
?>

...如果我从命令行以这种方式运行它:

... and if I run it from the command line this way:

\php\php.exe  mathex.php  

...然后我得到这些结果:

...then I get these results:

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






Nota Bene

我尝试使用.NET 4.0编译的程序集执行此操作,但它确实不起作用,给我一个关于.NET运行时不匹配的错误消息。像这样:

I tried doing this with an assembly compiled with .NET 4.0, but it did not work, giving me an error message about a .NET runtime mismatch. Like this:

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 表示运行时不匹配 - 程序集的运行时版本与尝试加载程序集的应用程序的运行时版本不匹配。

The 0x8013101b indicates a runtime mismatch - the runtime version of the assembly does not match the runtime version of the app that is trying to load the assembly.

从此我得出结论,php5被编译为支持.NET 2.0(包括3.0和3.5)。 .NET 4.0的运行时版本已更改,因此使用.NET 4.0编译器(包括VS2010)编译的程序集将无法与php5.exe一起使用。解决方法是使用.NET 2.0或3.5编译器(VS2005,vs2008)进行编译。

From this I conclude that php5 is compiled to support .NET 2.0 (which includes 3.0 and 3.5). The runtime version changed for .NET 4.0, so assemblies that you compile with a .NET 4.0 compiler (including VS2010) will not be usable with php5.exe. The workaround is to just compile with the .NET 2.0 or 3.5 compiler (VS2005, vs2008).

这篇关于麻烦使用PHP的DOTNET。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆