【问题标题】:Invoke a matlab method in C# code with parameters在 C# 代码中使用参数调用 matlab 方法
【发布时间】:2019-10-21 15:36:53
【问题描述】:

我试图在我的 C# 代码中使用参数调用 matlab 方法。我使用反射在运行时将带有 matlab 函数的 dll 加载到我的应用程序中,效果很好:

Assembly matlabAssembly = Assembly.LoadFrom(info.FullName);

List<Type> types = new List<Type>();

types = matlabAssembly.GetTypes().ToList();

List<MethodInfo> methods = new List<MethodInfo>();
methods.AddRange(types[0].GetMethods());

dynamic dynamicObject = Activator.CreateInstance(types[0]);

dll包含一种类型和一种功能:

MWArray MyMatlabFunction(MWArray, MWArray, MWArray, MWArray);

我创建了几个数组并希望将它们作为参数传递给这个函数。为了使 MWArray 类型在编译时可用于 C#,我将 Matlab 运行时中的程序集“MWArray.dll”静态添加到我的项目中。

MWArray array1 = new MWNumericArray(120);
MWArray array2 = new MWNumericArray(100);
MWArray array3 = new MWNumericArray(15);
MWArray array4 = new MWLogicalArray(true);
object[] params = new object[] {array1, array2, array3, array4};

MethodInfo matlabFuncion = methods[5]; //MyMatlabFunction

matlabFunction.Invoke(dynamicObject, params);

当我调用调用方法时,我得到一个异常,即 MWNummericArray 无法转换为 MWArray 尽管 MWNummericArray 直接派生自 MWArray。我错过了什么还是我做错了?

【问题讨论】:

    标签: c# matlab reflection invoke method-parameters


    【解决方案1】:

    如果有人偶然发现同样的问题,这里是我找到的解决方案:

    当您想在您的 C# 应用程序中运行 Matlab 代码时,您需要从 Matlab 运行时引用“MWArray.dll”。但是,如果您将此 dll 的引用静态添加到您的项目中,它将无法正常工作,因为无法加载该引用。

    解决方案是通过反射加载对“MWArray”的引用并动态创建实例到“MWArray”。

    public void Foo()
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
    
        // Load dll which was exported from Matlab into application
        string path = @"..\..\..\..\MatlabDlls\Matlab-Integration";
        string dllName = "MyExportedMatlabDLL.dll";
        List<string> dllPaths = Directory.GetFiles(path).Where(file => file.EndsWith(dllName)).ToList();
    
        FileInfo info = new FileInfo(dllPaths[0]);
        Assembly matlabAssembly = Assembly.LoadFrom(info.FullName);
    
        // Get types from exported dll
        List<Type> exportedMatlabTypes = new List<Type>();
        exportedMatlabTypes = matlabAssembly.GetTypes().ToList();
    
        List<MethodInfo> methods = new List<MethodInfo>();
        methods.AddRange(exportedMatlabTypes[0].GetMethods());
    
        // Create instance of exported Matlabtype 
        dynamic dynamicObject = Activator.CreateInstance(exportedMatlabTypes[0]);
    
        // Select MWArray from loaded Assemblies
        // Important: MWArray could only be loaded into the application with
        // the ResolveEventHandler further below
        Assembly mwArrayAssembly = AppDomain.CurrentDomain.GetAssemblies().Where(name => name.FullName.Contains("MWArray")).ToList()[0];
    
        // Get all available types of MWArray
        List<Type> MWArrayTypes = mwArrayAssembly.GetTypes().ToList();                          
    
        // Create some MWArrays
        // MWNummericArray
        dynamic array1 = Activator.CreateInstance(MWArrayTypes[9], new object[] { new byte[640 * 480]});
        //MWNummericArray
        dynamic array2 = Activator.CreateInstance(MWArrayTypes[9], new object[] { 100 });
        //MWLogicalArray
        dynamic array3 = Activator.CreateInstance(MWArrayTypes[5], new object[] { true });
    
        // Parameters for Matlab function 
        object[] params= new object[] { array1, array2, array3};
    
        MethodInfo matlabFuncion = methods[5];      
        var result = matlabFuncion.Invoke(dynamicObject, params);
    }
    
    // The ResolveEventHandler ensures the proper loading of dependent assemblies
    // I wrote a crawler that would search inside the Matlab runtime for dependent 
    // assemblies. It is enough to just load "MWArray" from a static path... 
    private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
    {
        Assembly dependentAssembly = null;
        string assemblyName = args.Name.Split(',')[0];
        string assemblypath = _crawler.getFullName(_runtimepath, assemblyName);
        if (assemblypath != string.Empty)
            dependentAssembly = Assembly.LoadFile(assemblypath);
        return dependentAssembly;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-13
      • 2016-08-17
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 2019-05-05
      相关资源
      最近更新 更多