4

PHP から com 経由で .net アセンブリを呼び出そうとしています (DOTNET() を使用)。PHPはDLLを見つけて適切に初期化しているようですが、何らかの理由でメソッドを表示/使用できません。どうすればこれを修正できるか知っている人はいますか?

.net クラスを呼び出すために使用している php コードを次に示します。私がそれを呼び出すと、出力は「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;
        }
    }

} 
4

1 に答える 1

8

get_class_methods()Dotnetクラスオブジェクトでは機能しません。これはプロキシであり、通常のphpオブジェクトのようには動作しません。

オブジェクトのメソッドの一覧表示に本当に集中している場合は、.NETオブジェクトへのIDispatchの実装を検討する必要があります。ただし、主な目標が単に.NETオブジェクトを使用することであり、メソッドを一覧表示する試みが、それが機能しなかった理由診断するための単なる副次的な作業であった場合は、いくつかの提案があります。

  1. を使用するのではなくgacutil、必要なDLLをphpディレクトリ(php.exeが存在する場所)に挿入できるかどうかを検討してください。にある場合php.exec:\php5\php.exe、アセンブリをにコピーしますc:\php5

  2. 上記の提案に従う場合、.NETアセンブリに厳密な名前を付ける必要はありません。GACを計画している場合は、厳密に名前を付ける必要があります。私が言ったように、phpでロードするためにGACする必要はありません。アセンブリをPHPディレクトリにコピーすると、署名されていないアセンブリを使用できます。

  3. これを使用した初期の開発と調査では、php.exeIISを使用してWebリクエストを介してphpを起動するのではなく、コマンドラインからプログラムを使用します。これにより、IISからの500エラーを心配することなく、エラーメッセージを直接確認できます。


これが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.

次に、次の内容のmathex.phpという名前の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を含む)をサポートするようにコンパイルされていると結論付けます。ランタイムバージョンが.NET4.0で変更されたため、.NET 4.0コンパイラ(VS2010を含む)でコンパイルしたアセンブリは、php5.exeでは使用できなくなります。回避策は、.NET 2.0または3.5コンパイラ(VS2005、vs2008)でコンパイルすることです。

于 2012-06-03T03:32:31.870 に答える