Everytime I call a Matlab function in C#, it has to open the Workspace window first. Is there any way to execute a function without displaying the Workspace? Here's my C# code:
MLApp.MLApp matlab = new MLApp.MLApp();
matlab.Execute(#"cd C:\path\to\folder");
object BestIter = null;
object BestPosition = null;
matlab.PutWorkspaceData("npop", "base", this.Npop);
matlab.PutWorkspaceData("maxiter", "base", this.MaxIter);
matlab.Execute("[bestiter, bestposition] = Algorithm(maxiter, npop);");
matlab.GetWorkspaceData("bestiter", "base", out BestIter);
matlab.GetWorkspaceData("bestposition", "base", out BestPosition);
You may try to compile your Matlab function code using compiler.
After that, you execute your MATLAB .exe file in C# environment using:
Process.Start("yourfile.exe")
Related
I embed an IronPython interpreter in a C# application to execute a Python script. The script evaluates a specific environment variable VAR1 using os.environ['VAR1']
I need to change the value of VAR1 temporarily before the script is executed. To do this I call
Environment.SetEnvironmentVariable("VAR1", "NEW_VALUE");
in the C# code. Unfortunately this does not work. The Python script still "sees" the old value of VAR1 (the value it had when the hosting C# application started).
Here is a complete example code:
Environment.SetEnvironmentVariable("VAR1", "NEW_VALUE");
var engine = Python.CreateEngine();
engine.SetSearchPaths(new string[] { #"c:\Program Files (x86)\IronPython 2.7\Lib\" });
var ms = new MemoryStream();
engine.Runtime.IO.SetOutput(ms, Encoding.Unicode);
var script = engine.CreateScriptSourceFromString("import os\nprint os.environ['VAR1']");
script.Execute();
System.Windows.Forms.MessageBox.Show(Encoding.Unicode.GetString(ms.ToArray()));
My understanding is that the IronPython engine runs in the same process as the C# host application. If this is correct, how can the Python code and the C# code see different environment variables?
Is there a better (working) way to set an environment variable for the Python script?
Well, I still don't know why the above code doesn't work but one can simply set an environment variable in the Python environment by executing Python code that sets the variable BEFORE executing the real code:
engine.CreateScriptSourceFromString("import os\nos.environ['VAR1'] = 'NEW_VALUE'").Execute();
var CodeIReallyWantToRun = engine.CreateScriptSourceFromFile(...);
CodeIReallyWantToRun.Execute();
I am currently stuck while trying to call a c# methods from python. I am using python 3.2 and not IronPython. I used pip to install the latest version of python.net
Problem occurs (as often discussed) while using ref or out parameters.
Here is my code so far:
import clr
path = clr.FindAssembly("USB_Adapter_Driver")
clr.AddReference(path)
from USB_Adapter_Driver import USB_Adapter
gpio = USB_Adapter()
version2 = ''
status, version = gpio.version(version2)
print ('status: ' + str(status))
print ('Version: ' + str(version))
readMask = bytearray([1])
writeData = bytearray([0])
print (readMask)
print (writeData)
status, readData = gpio.gpioReadWrite(b'\x01',b'\x00',b'\x00')
status, readData = gpio.gpioReadWrite(readMask[0],writeData[0],b'\x00')
status, readData = gpio.gpioReadWrite(readMask[0],writeData[0],)
I have had some major issues getting clr. running at all. But in this exact config it seems to work (I need to save the path to a variable, otherwise it wont work, I also cant type the path the dll in clr.AddReference(path) because this wont work as well)
The c# version method looks like this:
public USB_Adapter_Driver.USB_Adapter.Status version(ref string ver)
My status variable gets a value which works perfectly with the status enum for the c# class.
Problem is: after the call my variable "version" is empty. Why? According to: How to use a .NET method which modifies in place in Python? this should be a legal way to do things. I also tried to use the explicit version but my namespace clr does not contain clr.Reference().
The next (and more severe) problem is pio.gpioReadWrite().Here the info about this one:
public USB_Adapter_Driver.USB_Adapter.Status gpioReadWrite(byte readMask, byte writeData, ref byte readData)
Here I get the error message:
TypeError: No method matches given arguments
It doesn't matter which of the calls I use from above. All of them fail.
Here is the full output of a debugging run:
d:\[project path]\tests.py(6)<module>()
status: 6
Version:
bytearray(b'\x01')
bytearray(b'\x00')
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
d:\[project path]\tests.py(28)<module>()
status, readData = gpio.gpioReadWrite(readMask[0],writeData[0],)
(Pdb) Traceback (most recent call last):
File "D:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\pdb.py", line 1661, in main
pdb._runscript(mainpyfile)
File "D:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\pdb.py", line 1542, in _runscript
self.run(statement)
File "D:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\bdb.py", line 431, in run
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "d:\[project path]\tests.py", line 28, in <module>
status, readData = gpio.gpioReadWrite(readMask[0],writeData[0],)
TypeError: No method matches given arguments
Hope one of you has an idea on how to fix this.
Thanks,
Kevin
Python.Net doesn't handle ref/out parameters like IronPython.
status, readData = gpio.gpioReadWrite(b'\x01',b'\x00',b'\x00') call is not quite correct since Python.Net will not return an updated readData as second result.
You can handle ref parameters using reflection. Check out my answer to similar question here
there is a rough code template for your case:
import clr
clr.AddReference("USB_Adapter_Driver")
import System
import USB_Adapter_Driver
myClassType = System.Type.GetType("USB_Adapter_Driver.USB_Adapter, USB_Adapter_Driver")
method = myClassType.GetMethod("gpioReadWrite")
parameters = System.Array[System.Object]([System.Byte(1),System.Byte(0),System.Byte(0)])
gpio = USB_Adapter_Driver.USB_Adapter()
status = method.Invoke(gpio,parameters)
readData = parameters[2]
I tried to call some Matlab functions from C# code (.NET) using PutFullMatrix() & GetFullMatrix().
I found that it worked well for passing arrays to the Matlab functions and finishing the calculation in the Matlab files.
The matlab files can also return the correct answer to C# when the return value is scalar (i.e. 1*1 matrix). But when I tried to return an 1*n matrix from Matlab to C#, it always ended up with an exception in Visual studio. It's a type of "System.Runtime.InteroServices.COMException" from mscorlib.dll.
I tried to simplify the function down to a matrix addition, still no luck. Can anyone shed light on why this fails? I am using .NET 4.5 runtime target for x86 CPU.
Below is my problematic C# code:
// Instantiate MATLAB Engine Interface through com
MLApp.MLApp matlab = new MLApp.MLApp();
matlab.PutFullMatrix("basebandData", "base", IData, QData);
matlab.PutFullMatrix("sample_rate", "base", SampleRateR,SampleRateI);
// Using Engine Interface, execute the ML command
// contained in quotes.
matlab.Execute("cd c:\\Users\\****\\Desktop\\MatlabFunctionfolder;");
matlab.Execute("open MATLABFunction.m");
matlab.Execute("dbstop in MATLABFunction.m");
matlab.Execute("[RespRate, HeartRate, HRWav, status]=MATLABFunction(basebandData,sample_rate);");
// matlab.Execute("com.mathworks.mlservices.MLEditorServices.closeAll");
matlab.GetFullMatrix("RespRate", "base", ref RespRateR, ref RespRateI);
matlab.GetFullMatrix("HeartRate", "base", ref HeartRateR, ref HeartRateI);
matlab.GetFullMatrix("HRWav", "base", ref HRWavR,ref HRWavI); // the line where the exception pop up, if don't try to return the array HRWav from matlab function (RespRate, HeartRate, and Status are all 1x1 matrices) the code services well.
matlab.GetFullMatrix("status", "base", ref StatusR, ref StatusI);
I am using some matlab functions in c#. When I convert a function to dll, I have two dll. One is Entropy.dll and other one is EntropyNative.dll.
If I use the Entropy.dll I must install the matlab compiler runtime (MCR) to the target computer because it needs MWArray class and it only works with MCR. However I do not want to install MCR to target computer so I have tried to use the EntropyNative.dll because it takes Object instead MWArray as parameter. Thus I do not need to install MCR to each computer. However when I use the native dll, MWMCR:EvaluateFunction error. occurs. That means out of memory exception. File size and functions are same but why this error occurs when I use the native dll?
This (Entropy.dll) one works and error not occurs.
MWNumericArray arr1 = null;
Entropy ent = new Entropy(); //Matlab function.
while(true)
{
double[] arraySegment = new double[window];
arr1=arraySegment;
MWArray function1Result = ent.function1(arr1);
MWArray function2Result = ent.function2(arr1);
arr1=null;
}
If I use EntropyNative.dll out of memory error occurs
Entropy ent = new Entropy();
while(true)
{
double[] arraySegment = new double[window];
double function1Result = ent.function1(arraySegment);
double function2Result = ent.function2(arraySegment);
}
I want to use Native dll so how can I eliminate this error? I tried to force GarbageCollector but it does not help me. Also I have tried ent.WaitForFiguresToDie() and ent.Dispose().
ent.WaitForFiguresToDie():
This method will cause a MATLAB figure window to behave as a modal
dialog box. The method will not return until all the figure windows
associated with this component have been closed.
I'm wondering if there is a possibility to call a specific Method from a Python script over a C# project.
I have no code... but my idea is:
Python Code:
def SetHostInfos(Host,IP,Password):
Work to do...
def CalcAdd(Numb1,Numb2):
Work to do...
C# Code:
SetHostInfos("test","0.0.0.0","PWD")
result = CalcAdd(12,13)
How can I call one of the Methods, from this Python script, over C#?
You can host IronPython, execute the script and access the functions defined within the script through the created scope.
The following sample shows the basic concept and two ways of using the function from C#.
var pySrc =
#"def CalcAdd(Numb1, Numb2):
return Numb1 + Numb2";
// host python and execute script
var engine = IronPython.Hosting.Python.CreateEngine();
var scope = engine.CreateScope();
engine.Execute(pySrc, scope);
// get function and dynamically invoke
var calcAdd = scope.GetVariable("CalcAdd");
var result = calcAdd(34, 8); // returns 42 (Int32)
// get function with a strongly typed signature
var calcAddTyped = scope.GetVariable<Func<decimal, decimal, decimal>>("CalcAdd");
var resultTyped = calcAddTyped(5, 7); // returns 12m
I found a similar way to do it, the call of the method is much easier with it.
C# Code goes as follows:
IDictionary<string, object> options = new Dictionary<string, object>();
options["Arguments"] = new [] {"C:\Program Files (x86)\IronPython 2.7\Lib", "bar"};
var ipy = Python.CreateRuntime(options);
dynamic Python_File = ipy.UseFile("test.py");
Python_File.MethodCall("test");
So basically I submit the Dictionary with the Library path which I want to define in my python file.
So the PYthon Script looks as follows:
#!/usr/bin/python
import sys
path = sys.argv[0] #1 argument given is a string for the path
sys.path.append(path)
import httplib
import urllib
import string
def MethodCall(OutputString):
print Outputstring
So The method call is now much easier from C#
And the argument passing stays the same.
Also with this code you are able to get a custom library folder
for the Python file which is very nice if you work in a network
with a lot of different PC's
You could make your python program take arguments on the command line then call it as a command line app from your C# code.
If that's the way to go then there are plenty of resources:
How do I run a Python script from C#?
http://blogs.msdn.com/b/charlie/archive/2009/10/25/hosting-ironpython-in-a-c-4-0-program.aspx