Call matlab shared library from dotnet core on linux - linux

I am trying to call a shared library created with MathWorks MATLAB Compiler SDK from C# (.NET Core) running on a Linux container.
I have a matlab .m file that I've compiled into a .dll using the MATLAB R2018b compiler SDK. Because the final execution environment is .NET Core 2.2 running on a Linux container I chose the "C Shared Library" option. I call that shared library using the DLLImport mechanism of .NET.
Here is some code from my project. This code is KISS-level because I need to understand how to integrate MATLAB and C# on Linux before I start on the main project.
haveSomePi.m
function hal = haveSomePi()
hal = 3.1415;
end
MyMath.h
extern LIB_MyMath_C_API bool MW_CALL_CONV mlfHaveSomePi(int nargout, mxArray** hal);
MyMathWrapper.cs
[DllImport("MyMath.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void mlfHaveSomePi(int nargout, ref IntPtr hal);
MyMathWrapperTests.cs
[TestMethod]
public void ShouldReturnPi()
{
var hal = IntPtr.Zero;
MyMathWrapper.mlfHaveSomePi(1, ref hal);
double result = (double)hal;
Assert.AreEqual(3.1415, result, 1e-5);
}
The expected result is that the assert in the test method passes. It fails because trying to cast an IntPtr to a double doesn't make sense in this context. I'm sure there is a way to de-reference the IntPtr to get at the underlying double, I just haven't found that particular nugget of information.
I have been successful when compiling the .m file into a .NET library and into a COM object. I don't think I can use either of those libraries on Linux because of differences in the binary load/link format for each OS. When calling the method in the COM object I was able to directly cast the IntPtr to a double, there must be some marshaling magic going on in the background.
Is the method signature for the DLLImport statement correct? Do I map mxArray** to IntPtr?
How do I get the double from the IntPtr? Copy a block of memory into a managed byte array and cast?
My ultimate goal is to access a large signal processing library of matlab code from dotnet. The matlab code uses a lot of vectors and arrays so getting those into and out of the unmangaged library is my next hurdle.
Best regards.

I'm not a mathlab user, so I might be wrong, very wrong!
Getting Linux .dll equivalent
What you need, is the correct shared library/object for the run-time OS to be exported from mathlab.
Windows: .dll = Dynamic Link Library
Linux: .so = shared object [.net core butter and bread for Linux]
Instruction to get .so exported lib from mathlab
Compile your MATLAB files into a shared library (on UNIX)
mcc -t -L C -W MyMath-T link:lib haveSomePi.m libmmfile.mlib
Resulting MyMath.so, MyMath.exports, MyMath.h and MyMath.mlib, more details here
Binding Assembly
Make sure you have MyMath.so file next to MyMath.dll file, (bin, app data or where is needed)
Custom "NativeLibraryLoader" can be used to load different shared lib files based on OS, written by a GIT user because .net core din't had any (link). I would say is a bit over-complicated, but is your choice.
[DllImport] can be used instead!
DllImport without extension, supported on Windows and Linux and MAC will import the appropriate library for the target platform.
[DllImport("MyMath")]
Use <dllmap/> to map an import library name to the target platform library name. For MyMath.dll the corresponding Linux .so should be MyMath.so (more here)
[DllImport("MyMath.dll")]
Config map in csproj
<configuration>
<dllmap dll="MyMath.dll" target="MyMath.so" />
</configuration>

I think the main concern here is that you are doing
C Shared Library
Which is NOT C#...
Instead you should be doing
.NET Assembly
https://in.mathworks.com/help/compiler_sdk/gs/create-a-dotnet-application-with-matlab-code.html
It's important to note that .NET Core is not supported either, and you will have to change your project to a "classic" .NET Framework (If I recall correctly, at least 4.x)

Related

how can I link a dll to fortran (visual studio)?

I have some DLLs that I want to use in a FORTRAN Project in VISUAL STUDIO but I can't find how.
Here is a simple code I'm using to find out how.
Using visual studio I created a DLL from this
subroutine printing
!DEC$ ATTRIBUTES DLLEXPORT::printing
print*,"dll naimi created"
end subroutine printing
I added the link of the DLL to project>properties>Linker>General>Additional Library directories
Main program:
program Console11
implicit none
call printing
end program Console11
ERROR : Error 1 error LNK2019: unresolved external symbol _PRINTING referenced in function _MAIN__.
other solutions related to this suggest using the .lib created while generating the DLL, but in my real case I only have the DLLs without their .lib.
So how to use a DLL ... ?
You appear to be trying to use a DLL as an input file to the linker.
(You also appear to be trying to specify a file for a linker option that takes a directory. To specify an additional input file for the linker, either add the file to the project just like you would attach a source file, or use the "Linker > Input > Additional dependencies" project property. The property you mention in your post then tells the linker where (which directories) to search for those additional dependencies.)
Unlike the unix convention, you do not link against DLLs when building executables and other DLLs on Windows. The DLL typically does not contain the necessary information for the linker - instead that information is contained in an import library (which is just a variation of a typical .lib static library) or equivalent.
If you were able to successfully build a DLL, then you will probably find the import library for that DLL in the same directory as the DLL. Supply that import library as an additional dependency for projects that require the DLL.
When you link an EXE or other DLL using an import library on Windows, the target DLL is automatically loaded by the operating system when your executable code is loaded. This is called load time dynamic linking.
If you do not have the import library for a DLL, then your choices are:
Ask the person who built the DLL for the import library.
Reference the DLL using run time dynamic linking, rather than load time. This means that you use the Windows API functions LoadLibrary, GetProcAddress and friends in your program to explicitly tell the operating system to load a particular DLL and to obtain the address of a function pointer. If you are using Intel Fortran, then complete examples of this are installed with the compiler - see in the file "C:\Program Files (x86)\IntelSWTools\samples_2016\en\compiler_f\psxe\DLL.zip" or similar.
Generate an import library from the minimum information in the DLL, plus other information about the DLL that you may have. One approach to this is to write a module definition file (.def) for the DLL, and then use the LIB utility to turn that def file into an import library. See How to make a .lib file when have a .dll file and a header file for an example.

Interoperability C # and NAV 2016

I'm around trying to create an interoperable dll written in C # for use in Microsoft NAV 2016, for the development of a fiscal printer driver.
In my C # project I called to other functions dll (delivered by the company Bematech, in 32-bit and unmanaged).
Calls to the functions of the dll unmanaged (and tested from an .EXE) I make as follows:
[DllImport ( "BemaFi32.dll")]
public static extern int Bematech_FI_ProgramaAlicuota (Aliquot string, int ICMS_ISS);
When I try to run it from the NAV2016 I get the following error: .A call to "MyAssembly" failed with this message: You are trying to load a program with an incorrect format. Expection from HRESULT: 0x8007000B
I guess the error because the dll is not managed or 32-bit version (if that's the problem becomes more difficult because apparently there is no 64-bit version). Not how to solve the problem.
NAV cannot work with unmanaged code.
The only way is to write a wrapper dll which can be called from NAV.
Microsoft is doing the same with the Office SDK for example...
Cheers!
The problem was not the embedded dll unmanaged, was that the new dll to be 32 bit was not compatible with the client NAV, the solution was to change the 32bit client as follows:
Rename the file to Microsoft.Dynamics.Nav.Client.X64.exe Microsoft.Dynamics.Nav.Client.exe, and then a Microsoft.Dynamics.Nav.Client.X86.exe rename the file to Microsoft.Dynamics.Nav.Client. exe.
and the C / AL change in the variable declared the call to the dll
Property Value
Yes RunOnClient

How to get a reference to the JVM from a native android executable?

I've successfully built and run a native executable using the NDK. It is a regular C++ application with no java entry point (e.g., no xyz_activity, just int main()). Now I need to access some methods from the android runtime through JNI, but i can't seem to get a hold of the JavaVM*. jni_getcreatedjavavms isn't exported by the NDK, and neither is AndroidRuntime::getJavaVM(). So that leaves me with JNI_OnLoad which is only called for shared libraries. I already tried splitting the project up into an executable and a .so file containing JNI_OnLoad, but I guess that only works when doing an explicit System.loadLibrary call. However the project doesn't contain any java code at all. How do I obtain a reference to the JVM?
As answered here you can access JVM using jni environment (JNIEnv):
JavaVM* jvm;
int gotVM = (*jniENV).GetJavaVM(&jvm);

Visual C++ Release build - is string getting corrupted when passed across DLL because compiled with different runtime version?

After building in Release mode, I am seeing exceptions which didn't occur in Debug mode. When debugging the release build, it looks like string references are not being passed correctly from the EXE (our application) to the DLL which is receiving the string reference.
Our EXE code looks like this:
string contents = "handle_message(): received=" + msg->encode();
LOG4CXX_DEBUG(logger, contents);
The LOG4CXX_DEBUG is going to log4cxx.dll, whose code looks like this:
CharMessageBuffer& CharMessageBuffer::operator<<(const std::basic_string<char>& msg) {
if (stream == 0) {
buf.append(msg);
} else {
*stream << msg;
}
return *this;
}
Looking at the Call Stack in the debugger, when I navigate down to the frame which has our source, I can see that contents is a valid string with size=583, capacity=838.
In the frame inside the log4cxx.dll (the next frame above in the stack) the string reference shows size=838, capacity=363113231 (and the values are all garbage).
Both our app and log4cxx.dll were compiled on the same machine, using the same runtime settings (/MD), but different versions of Visual Studio. The log4cxx dll was compiled using Visual Studio 2008 and our application was compiled using Visual Studio 2010. Running dumpbin on the 2 objects shows:
Our App (EXE)
MSVCP100.dll
MSVCR100.dll
log4cxx.dll (DLL)
MSVCP90.dll
MSVCR90.dll
Is this problem due to the fact that they are using different runtime versions?
If you pass non-POD (plain old datatypes) between DLL/EXE boundaries (like STL string or CRT FILE pointers) you must use the same shared CRT.
In your case, you must recompile all DLLs/LIBs with the same compiler!
See also: I can pass std::string for a Dll and what i can do with DLL´s?
The implicit question is:"Is there a way to pass data, hopefully using string and other STL containers, to DLLs of another version of visual studio either previous or later than the one that I'm using?".
Aside from using POD, there are probably three approaches: shared memory, sockets( to local host ) and MSMQ. All of these methods require additional extensive programming, but the deeper answer is found in how the interface is changing the input parameter.
I have found a possible solution to the string passing problem on the internet. It removes one layer of corruption; cast a pointer to the container to a uint and pass the uint. Dereference the uint to the pointer and the object is revealed. Beware, auto_ptrs are usually deleted in this process, so don't use them. If the passed object is still offset incorrectly( this happened to me with VS08 passing to a VS13 ), then pass the c_str() of the string instead. It's certainly inelegant, but we need to know all the alternatives. See "HowTo: Export C++ classes from a DLL" in Code Project( Nov 22, 2012 ).

Platform independent resource management [duplicate]

This question already has answers here:
Is there a Linux equivalent of Windows' "resource files"?
(2 answers)
Closed 4 years ago.
I'm looking for a way to embed text files in my binaries (like windows resource system). I need something thats also platform independent (works in windows and linux). I found Qt resource management to be what I need but I'm not keen on my app depending on Qt for this alone. I also found this tool at http://www.taniwha.com/~paul/res/ .. but it is too platform specific.
The xxd utility can be used to create a C source file, containing your binary blobs as an array (with the -i command line option). You can compile that to an object which is linked into your executable.
xxd should be portable to most platforms.
If you're using QT 4.5, you can make sure that program is only dependent on one small piece of QT, such as libqtcore. QResource is a part of libqtcore.
You can simlpy append all kinds of data to your normal binary. Works in both Windows and Linux. You'll have to open your own binary at runtime and read the data from there.
However, I have to agree that embedding data in binaries is a strange idea. It's common practice to include such data as separate files packaged with the application.
That is not such a great idea. On Linux, for example, data is expected to be installed in a subdirectory of "$datadir" which is, by default, defined to be "$prefix/share", where "$prefix" is the installation prefix. On Mac OS X, resources are expected to be installed in $appbundle/Contents/Resources, where $appbundle is the name of the folder ending in ".app". On Windows, installing data in a folder that is a sibling of the executable is not an uncommon practice. You may be better off using the CMake build system, and using its CPack packaging features for installing/bundling in the default, preferred platform-specific manner.
Although bundling your resources into the executable, itself, may seem cool, it is actually a dangerous idea... for example, will the embedded data be allocated in an executable page? What will happen if you attempt to overwrite or modify the data? What if you want to tweak or modify the data at runtime? Things to think about.
This looks very promising: https://github.com/cyrilcode/embed-resource
CMake based and platform-independent.
As I also do not like the idea of converting files into C arrays only to have them converted back to binaries, I created my own resource compiler using LLVM and Clang:
https://github.com/nohajc/resman
I tested it on Windows, Linux and macOS but it can potentially be run on any platform supported by LLVM.
It is used like this:
Create header file, e.g. res_list.h
#pragma once
#include "resman.h"
// Define a global variable for each file
// It will be used to refer to the resource
constexpr resman::Resource<1> gRes1("resource_file1.jpg"); // resource with ID 1
constexpr resman::Resource<2> gRes2("resource_file2.txt"); // resource with ID 2
constexpr resman::Resource<3> gRes3("resource_file3.mp3"); // resource with ID 3
...
Run resource compiler
$ rescomp res_list.h -o res_bundle.o
Link res_bundle.o to your project
Use the resource files
#include "res_list.h"
...
resman::ResourceHandle handle{gRes1};
// ResourceHandle provides convenient interface to do things like:
// iterate over bytes
for (char c : handle) { ... }
// convert bytes to string
std::string str{handle.begin(), handle.end()};
// query size and id
unsigned size = handle.size();
unsigned id = handle.id();
The resource compiler parses res_list.h (using Clang) but instead of generating cpp files, it goes straight to the native object file (or static library) format (using LLVM).

Resources