Вызвать метод Matlab в коде C # с параметрами - PullRequest
0 голосов
/ 21 октября 2019

Я пытаюсь вызвать метод matlab в моем коде C # с параметрами. Я использовал отражение, чтобы загрузить dll с функцией matlab во время выполнения в мое приложение, которое прекрасно работает:

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 # во время компиляции, я статически добавил сборку "MWArray.dll" из среды выполнения Matlab в мой проект.

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);

Когда я вызываю метод invoke, я получаю исключение, что MWNummericArray не может быть преобразован в MWArray, хотя MWNummericArray напрямую происходит от MWArray. Я что-то упускаю или делаю это совсем не так?

1 Ответ

0 голосов
/ 23 октября 2019

Если кто-то сталкивается с той же проблемой, вот решение, которое я нашел:

Когда вы хотите запустить код Matlab в своем приложении C #, вам нужна ссылка на «MWArray.dll» из Matlabво время выполнения. Если вы добавите ссылку на эту 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;
}
...