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.
Related
Background
What I'm trying to do is to have a scoped variable of one of my models in the xaml.
In my workflow project "MyProject.Workflows" I have created model classes, code activities and Xaml files. They are all under same namespace. In another project ("Engine"), I load and execute these workflows.
To load the workflows in the "Engine", I use ActivityXamlServices with ActivityXamlServicesSettings including CompileExpressions = true.
When loading the ActivityXamlServices, I use a XamlXmlReader with XamlXmlReaderSettings where I actually point to the "MyProject.Workflows" dll.
Since Both these projects are in the same solution I actually referred MyProject.Workflows in the "Engine".
Because Earlier, they were in different solutions, So when I tried to do this It gave me It cant find the "MyProject.Workflows" dll even though I point it in the XamlXmlReaderSettings.
Then I tried to load the dll to the app domain and then it worked.But I did not want to deal with App Domains so I decided to get both projects under one solution so I can refer the "MyProject.Workflows" in the "Engine".
Issue:
If I use one of those models inside of the Xaml as an expression like "Assign Activity" the Workflow isn't getting compiled when I try to execute this.
For example if I use this in an "Assign" activity having a scoped variable of type MyObject
Newtonsoft.Json.JsonConvert.DeserializeObject<MyProject.Workflows.Models.MyObject>(inputString);
I will get the below error message when I run the workflow.
NotSupportedException:'Expression Activity type 'CSharpValue`1' requires compilation in order to run. Please ensure that the workflow has been compiled.
If I remove these objects and just deal with strings or ints, it works fine.
Things I found in my research:
I found this was a bug in .Net Framework 4.5. But Im using 4.6
Even though I used CompileExpressions = true , I tried this compile method I found. But did not change a thing.
private static void Compile(DynamicActivity dynamicActivity)
{
TextExpressionCompilerSettings settings = new TextExpressionCompilerSettings
{
Activity = dynamicActivity,
Language = "C#",
ActivityName = dynamicActivity.Name.Split('.').Last() + "_CompiledExpressionRoot",
ActivityNamespace = string.Join(".", dynamicActivity.Name.Split('.').Reverse().Skip(1).Reverse()),
RootNamespace = null,
GenerateAsPartialClass = false,
AlwaysGenerateSource = true,
};
TextExpressionCompilerResults results =
new TextExpressionCompiler(settings).Compile();
if (results.HasErrors)
{
throw new Exception("Compilation failed.");
}
ICompiledExpressionRoot compiledExpressionRoot =
Activator.CreateInstance(results.ResultType,
new object[] { dynamicActivity }) as ICompiledExpressionRoot;
CompiledExpressionInvoker.SetCompiledExpressionRootForImplementation(
dynamicActivity, compiledExpressionRoot);
}
I read that some people faced this problem and they had to actually move the models to a diffrent namespace. I did that too. Didn't fix the problem.
My Xaml file has this entry added at the top.
xmlns:local="clr-namespace:MyProject.Workflows.Models"
Can someone please help me to get through this?
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 trying to build a COM Library in C++, using a C# project for testing. Some methods need to return strings to the caller. On calling these methods from C# I get this: "Access violation reading at location ..."
This is the C++ code from my testproject (apart from all the stuff generated by VS 2010 ATL)
//COMTest.idl
[id(1)] HRESULT Test([out,retval] BSTR* ret);
//Program2.h
STDMETHOD(Test)(BSTR* ret);
//Program2.cpp
STDMETHODIMP CProgram2::Test(BSTR* ret)
{
BSTR tmp = (BSTR)CoTaskMemAlloc(sizeof(wchar_t) * 2);
tmp[0] = L'H';
tmp[1] = L'\0';
*ret = (BSTR)tmp;
return S_OK;
}
In C# I just referenced the DLL from the COM-Tab, turned "Embed Interop Types" off, because it caused errors, and ran this:
static void Main(string[] args)
{
COMTestLib.Program2Class instance = new COMTestLib.Program2Class();
string tmp = instance.Test(); //Where the error occurs
Console.WriteLine(tmp); //This is not reached
Console.Read();
}
The error occurs after leaving the Test-Method. I debugged the C++ code from within my C# project and the values are placed in the correct locations. I do not get the error if I try to return 0 (gives null in C#), even if I still allocate memory like in the example.
I can not make sense of the address, which the access violation complains about. It is neither the address I am allocating nor any other address used in the method. What also seems weird to me is that the CoTaskMemAlloc-Function always returns addresses with the first byte set to zero (0x00XXXXXX), but that might just be a COM thing.
I ran out of ideas and I cant find much information on this (except for basic COM tutorials) anywhere. Can anyone help?
BSTRs require extra memory (to keep track of the string len) so must use SysAllocString() function to allocate BSTRs (or use one of the "smart" BSTR classes).
So your original code should read like:
//Program2.cpp
STDMETHODIMP CProgram2::Test(BSTR* ret)
{
*ret = SysAllocString(L"H");
return S_OK;
}
A good reading about BSTRs: http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx
Check that your COM project and test project are both STA. Check the bitness too. What if you replace BSTR by LPSTR ?
My plan:
I'm trying to setup my C# project to communicate with Nodebox to call a certain function which populates a graph and draws it in a new window.
Current situation: [fixed... see Update2]
I have already included all python-modules needed, but im still getting a
Library 'GL' not found
it seems that the pyglet module needs a reference to GL/gl.h, but can't find it due to IronPython behaviour.
Requirement:
The project needs to stay as small as possible without installing new packages. Thats why i have copied all my modules into the project-folder and would like to keep it that or a similar way.
My question:
Is there a certain workaround for my problem or a fix for the library-folder missmatch.
Have read some articles about Tao-Opengl and OpenTK but can't find a good solution.
Update1:
Updated my sourcecode with a small pyglet window-rendering example. Problem is in pyglet and referenced c-Objects. How do i include them in my c# project to be called? No idea so far... experimenting alittle now. Keeping you updated.
SampleCode C#:
ScriptRuntimeSetup setup = Python.CreateRuntimeSetup(null);
ScriptRuntime runtime = new ScriptRuntime(setup);
ScriptEngine engine = Python.GetEngine(runtime);
ScriptSource source = engine.CreateScriptSourceFromFile("test.py");
ScriptScope scope = engine.CreateScope();
source.Execute(scope);
SampleCode Python (test.py):
from nodebox.graphics import *
from nodebox.graphics.physics import Vector, Boid, Flock, Obstacle
flock = Flock(50, x=-50, y=-50, width=700, height=400)
flock.sight(80)
def draw(canvas):
canvas.clear()
flock.update(separation=0.4, cohesion=0.6, alignment=0.1, teleport=True)
for boid in flock:
push()
translate(boid.x, boid.y)
scale(0.5 + boid.depth)
rotate(boid.heading)
arrow(0, 0, 15)
pop()
canvas.size = 600, 300
def main(canvas):
canvas.run(draw)
Update2:
Line 139 [pyglet/lib.py] sys.platform is not win32... there was the error. Fixed it by just using the line:
from pyglet.gl.lib_wgl import link_GL, link_GLU, link_WGL
Now the following Error:
'module' object has no attribute '_getframe'
Kind of a pain to fix it. Updating with results...
Update3:
Fixed by adding following line right after first line in C#-Code:
setup.Options["Frames"] = true;
Current Problem:
No module named unicodedata, but in Python26/DLLs is only a *.pyd file`. So.. how do i implement it now?!
Update4:
Fixed by surfing: link text and adding unicodedata.py and '.pyd to C# Projectfolder.
Current Problem:
'libGL.so not found'... guys.. im almost giving up on nodebox for C#.. to be continued
Update5:
i gave up :/ workaround: c# communicating with nodebox over xml and filesystemwatchers. Not optimal, but case solved.
-X:Frames enables the frames option as runtime (it slows code down a little to have access to the Python frames all the time).
To enable frames when hosting you just need to do:
ScriptRuntimeSetup setup = Python.CreateRuntimeSetup(new Dictionary<string, object>() {
{ "Frames", true }
});
Instead of the null that you're passing now. That's just creating a new dictionary for the options dictionary w/ the contents "Frames" set to true. You can set other options in there as well and in general the -X:Name option is the same here as it is for the command line.