Calling Matlab Compiler from inside C# app throws exception - c#

I found this code to invoke the Matlab compiler, it works fine when the function is called from Matlab command prompt, I build this function to .Net Assembly but whenever I try to use it in my C# app in order to build some .m file I get an exception, where do you think my problem is?
Matlab Code:
function compileCode(mfile,dllName , dnetdir)
%% Create directories if needed
if (exist(dnetdir, 'dir') ~= 7)
mkdir(dnetdir);
end
%% Build .NET Assembly
eval(['mcc -N -d ''' dnetdir ''' -W ''dotnet:' dllName ',' ...
'' dllName ',0.0,private'' -T link:lib ''' mfile '''']);
end
C# code:
var cmm = new compiler.MatlabCompiler();
MWCharArray x = new MWCharArray(#"C:\Users\ePezhman\Documents\MATLAB\Graph2D.m");
MWCharArray y = new MWCharArray("Graph");
MWCharArray z = new MWCharArray(#"C:\Matlab\dotnet");
cmm.compileCode(x,y,z);
Exception:
... MWMCR::EvaluateFunction error ... Undefined function 'mcc' for
input arguments of type 'char'. Error in => compileCode.m at line 9.
... Matlab M-code Stack Trace ...
at file C:\Users\ePezhman\AppData\Local\Temp\ePezhman\mcrCache8.0\compil0\compiler\compileCode.m,
name compileCode, line 9.

Interesting, I assume you are trying to compile a function that can dynamically compile other functions..
Unfortunately, I dont think the mcc function can be compiled/deployed itself
To be exact, the problem you are seeing is because MATLAB needs to know all functions called at compile-time, and by using eval, it wont figure it out on its own (since it wont parse inside the string). You can fix this particular issue by writing special comments for the compiler..
function myEval()
%#function foo
eval('...');
end
(Another alternative is using function handles).
Still even if you do that, it will fail at runtime inside the mcc function saying that: "License checkout failed, [...] Cannot find a valid license for Compiler".
The reason is as mentioned in the comments, mcc is a development tool and cannot be deployed to standalone programs which only depends on the free MCR runtime.
Think about it, if it was possible, it would defeat the whole purpose of buying licenses for the product, as you could create a standalone program that can compiler other codes without having the Compiler toolbox :)

Related

Call method from interface or abstract class within static void

I'm usually a javascript developer, but for my company I just started learning c# in order to use the CimatronE 13 API to develop custom command line PDM tools for this 3D modelling software.
As I'm making progress understanding the programming language, there's this frustrating situation where I want to use an API endpoint method but I can't manage to get it working.
The Cimatron documentation says the following:
IPdm::GetRelatedDocuments
Syntax: RelatedDocuments = GetRelatedDocuments ( DocumentPath );
This method allows you to get related files from compound types of files, for example Assembly or Drawing.
Input: (String) DocumentPath,
Path to file. For example \Documents\Location\Folder\Document. The file must be Assembly or Drawing.
Return: (Variant) RelatedDocuments,
Variant type array each element of which contain two dimensioned string type array of files related to selected one.
This looks pretty straight forward to me, so I tried calling it in multiple ways from within the static void Main() method, but I keep getting errors:
var RelatedDocuments = interop.CimBaseAPI.IPdm.GetRelatedDocuments("path");
CS0120: An object reference is required for the non-static field, method, or property 'IPdm.GetRelatedDocuments(string)'
interop.CimBaseAPI.IPdm pdm = new interop.CimBaseAPI.IPdm();
var RelatedDocuments = pdm.GetRelatedDocuments("path");
CS0144: Cannot create an instance of the abstract class or interface 'IPdm'
Any ideas? It's probably simple but I'm still a noob with c# :p
EDIT:
Cimatron documentation about the interface interop.CimBaseAPI.IPdm:
Properties:
Get
Query (String, DocumentEnumType, DocumentEnumUnit )
Variant
Methods:
A lot, including Variant GetRelatedDocuments ( String )
As how I see it now... interop.CimatronE.IPdm is an interface and in order to use it's methods, we first need access to the Cimatron application. Using the application object, we can use it's methods to get the desired interfaces such as IPdm and use their methods.
The following code gives no errors from the compiler but does when executing. This seems to be related to version 13 of CimatronE, since the application object works just fine using version 12. A lot has changed between these versions which I think is the reason the API is not functioning properly, outdated.
interop.CimAppAccess.AppAccess AppAcc = new interop.CimAppAccess.AppAccess();
interop.CimatronE.IApplication CimApp = /*(interop.CimatronE.IApplication)*/AppAcc.GetApplication();
interop.CimatronE.IPdm pdm = CimApp.GetPdm();
var RelatedDocuments = pdm.GetRelatedDocuments("path");
Console.WriteLine(RelatedDocuments);
Please correct me if I'm wrong! (since I just started and still learning c#)
I ran into this same issue with Cimatron 14.
I needed to make some changes in Visual Studio for things run properly with Cimatron.
Run Visual Studio in administrator mode
Set your Debug & Release Solution Platform to 'x64'
It was also recommended to point the build path for release & debug to the same folder as the Cimatron references. In my case 'C:\Program Files\3D Systems\Cimatron\14.0\Program'. However my code appears to run fine without this.
I created the Cimatron Application with this code (VB.Net):
Dim gAppAccess As New CIMAPPACCESSLib.AppAccess 'Define an AppAccess object to get running active application
Dim gApp As CIMAPPACCESSLib.Application 'Define an Application object
gApp = gAppAccess.GetApplication 'Getting running active application
If gApp Is Nothing Then
gApp = New CIMAPPACCESSLib.Application 'Creating a new instance of a Cimatron application
End If
References: Interop.CIMAPPACCESSLib.dll & interop.CimServicesAPI.dll
It is my understanding that Cimatron 15 may also requires some manifest changes.
There is some help information in the Cimatron program under Cimatrom Modules > Cimaton SDK that may be mildly helpful.

NReco Error: "The specified executable is not a valid application for this OS platform"

I'm using the NReco to convert videos. I declare the converter like the following, and add a handler to ConvertProgress.
Dim vid_Convert As New FFMpegConverter
AddHandler vid_Convert.ConvertProgress, Sub(sender, e) vidConvertProgress(folder,fname,fext,fverdest,fint,fcount,fhost,e)
vid_Convert.ConvertMedia(file_temp, Nothing, file_dest, "mp4", cSettings)
The media is converted fine. The problem is in the handler where I declare a new converter and have it do a GetVideoThumbnail (when the prior conversion is completed), like this:
Dim vid_Extract As New FFMpegConverter
vid_Extract.GetVideoThumbnail(inputFile, outputFile, extractposition)
This produces the error "The specified executable is not a valid application for this OS platform". However, I've executed the GetVideoThumbnail method by itself elsewhere in my program with no problem. For some reason, it won't work if it's executed within the handler. Is there a way around this?
I assume you use NReco.VideoConverter nuget package which embeds ffmpeg.exe and extracts it on first use. Most likely you call "ConvertMedia" and "GetVideoThumbnail" in parallel and this may cause incorrect extraction of ffmpeg.exe.
Workaround for this issue may be calling new FFMpegConverter().ExtractFFmpeg(); on the application start (in Program.cs) to guarantee that on "ConvertMedia" and "GetVideoThumbnail" calls ffmpeg is already extracted.

Go to library to C# | BadImageFormatException

I would like to create a library out of go-code and use it inside a C# winforms project.
For the error scroll to the bottom.
Setup
GO 1.10.2
tdm-gcc-5.1.0-3
Windows 10 / x64
Go-project called exprt
What I've tried
I've created a minimal go-tool that creates a file in the working-dir:
package main
import (
"os"
"C"
)
func main() {
// nothing here
}
//export Test
func Test() {
os.OpenFile("created_file.txt", os.O_RDONLY|os.O_CREATE, 0666);
}
The next steps were taken from Building a dll with Go 1.7.
I've then compiled to c-archive with the following command: go build -buildmode=c-archive which gives me exprt.a and exprt.h.
After that I've created a file called goDLL.c (1:1 as in the link above) and inserted this code:
#include <stdio.h>
#include "exprt.h"
// force gcc to link in go runtime (may be a better solution than this)
void dummy() {
Test();
}
int main() {
}
Lastly I've run this command to create my final dll:
gcc -shared -pthread -o goDLL.dll goDLL.c exprt.a -lWinMM -lntdll -lWS2_32
which gave me "goDLL.dll".
My problem
In C# I've created a winforms-project with 1 button that calls this declared function (copied the dll to the debug-folder):
[DllImport("goDLL.dll")]
private static extern void Test();
Error
System.BadImageFormatException: "An attempt was made to load a program with an incorrect format. (HRESULT: 0x8007000B)"
Sorry for that big block of text but this was the most minimal test I could think off.
I appreciate every help in here.
Well, in the given answer here https://social.msdn.microsoft.com/Forums/vstudio/en-US/ee3df896-1d33-451b-a8a3-716294b44b2b/socket-programming-on-64bit-machine?forum=vclanguage there is written:
The implementation is in a file called ws2_32.dll and there are 32-bit and 64-bit versions of the DLL in 64-bit Windows.
So the build as described in my question is correct.
Solution
The C#-Project has to be explicitly set to x64. AnyCPU won't work and throw the error shown in the question above.
Everything is working now. I'm leaving the question and answer as this is a full explanation of how to get go-code running out of C#.

import_type attempt to call global

I'm using the latest lua interface and trying to run this code
luanet.load_assembly("Phoenix")
luanet.load_assembly("Phoenix.Structures")
NpcDialog = luanet.import_type("Phoenix.Structures.NpcDialog")
function npc(request, client)
local dialog = new NpcDialog(client)
dialog.Text("hi this is a test")
dialog.Send()
end
but getting this error
LuaInterface.LuaException: [string "chunk"]:6: attempt to call global 'NpcDialog
' (a nil value)
the exe name is Map Server.exe
Assembly name Map Server
Default namespace Phoenix
it happens because the the assembly of the file different than the Assembly name and i don't know why!!
is there a way to make it work without changing the Assembly name
There is no new operator in Lua. Write:
function npc(request, client)
local dialog = NpcDialog(client)
If you still get same problem after this fix, then NpcDialog is nil: maybe return value of import is nil, or maybe it gets nilled between the import line and the line that calls npc(r,c). Maybe try
assert( NpcDialog )
If this fails meaning that load_assembly("Phoenix") failed, it's probably because the assembly is not called "Phoenix" but "Map Server", so try
luanet.load_assembly("Map Server")
NpcDialog = luanet.import_type("Phoenix.Structures.NpcDialog")
assert(NpcDialog)
Line 6 is valid Lua code but it does not do what you think. Lua parses it as if there was a ; after new, and so tries to call NpcDialog.

Embedding IronPython in a C# application - import error on urllib

I have a Python file with as content:
import re
import urllib
class A(object):
def __init__(self, x):
self.x = x
def getVal(self):
return self.x
def __str__(self):
return "instance of A with value '%s'" % (self.getVal())
I also have a simple C# console project with the following code:
engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromFile("test.py");
ScriptScope scope = engine.CreateScope();
ObjectOperations op = engine.Operations;
source.Execute(scope); // class object created
object klaz = scope.GetVariable("A"); // get the class object
object instance = op.Call(klaz, "blabla waarde"); // create the instance
object method = op.GetMember(instance, "getVal"); // get a method
string result = (string)op.Call(method); // call method and get result (9)
Console.WriteLine("Result: " + result); //output: 'Result: blabla waarde'
(I got this from this stackoverflow querstion and answer)
If I leave out the the import urllib statement in the Python file everything works fine. (meaning it finds the re module)
But as soon as i either add import urllib or import urllib2 I get the following exception:
ImportException was unhandled
No module named urllib
So somehow it can't find the urllib. I checked the IronPython lib folder and both urllib and urllib 2 are definitely there.
The same exception gets thrown when I import urllib in the C# code. (engine.ImportModule("urllib");)
Any ideas?
I'd like to manage the imports in the python code and not in the C# code.
(So I'd like to avoid stuff like this: engine.ImportModule("urllib");)
Edit:
Some extra info on what I'm actually going to use this for (maybe someone has an alternative):
I will have a main C# application and the python scripts will be used as extensions or plugins for the main application.
I'm using Python so that I don't need to compile any of the plugins.
I believe that 'Lib' being on sys.path from the interactive console is actually done inside ipy.exe - and when embedding you will have to add the path manually. Either the engine or the runtime has a 'SetSourcePaths' (or similar) method that will allow you to do this.
I face the same problem. Following "Tom E's" suggestion in the comments to fuzzyman's reply I could successfully resolve the issue. The issue seems to be it is not able resolve the location of the urllib.py. We need to set it.
You can check the following link for the question and answer.
The version of CPython you're importing from must match your IronPython version. Use CPython v2.5 for IronPython 2.0, or v2.6 for IronPython 2.6.
Try this:
import sys
sys.path.append(r'\c:\python26\lib') # adjust to whatever version of CPython you have installed.
import urllib

Categories