I want to load a C++ dll in C# (VS2012, C++ dll also created in VS2012 C++) that in C++ dll I've used a shared library generated by MATLAB with using of deploytool.(My configuration in both C# and C++ programs is x64 and shared library also generated in 64-bit version of MATLAB).
I've used following codes to load library and then I've recieved error code 1008 :
[DllImport("kernel32.dll",CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);
...
IntPtr handle = LoadLibrary("libName.dll");
if(handle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
//at this point error code will be 1008.
}
Help me to resolve that, please!
Thanks in advance.
Good chance the failure isn't directly in libName.dll but rather in one of its dependencies. There are quite a few tools that diagnose such dll loading problems:
Process monitor file system activity, can show you if a dll is sought but not found.
Dependency walker's 'profile' option can show you which dependent dll failed to load.
The most powerful tool AFAIK: 'Show Snaps' checkbox in gflags (bundled with debugging tools for windows). It activates a windows-loader-built-in tracing facility, that shows you not only who failed to load but also why exactly. Some more details and screenshots here.
Related
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)
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
I am porting a C++ project from an old Borland compiler to VisualStudio 2008. This project uses a third party DLL that I don't have the source code for, so I am unable to recompile or modify it. The header file for the DLL defines functions along the lines of:
extern "C" {
void __stdcall Init(int a, int b);
}
However when I try to link to this DLL, VisualStudio says that it cannot find the function _Init#8. When I look at the DLL I find that the function name is _Init, and not _Init#8 (it seems that the DLL to predates Microsoft adding #8 to stdcall name mangling).
My question is: How can I call funcions in this DLL? Does VisualStudio simply not support these old DLLs, or is there a flag/setting that I'm missing. (I am aware that I could use the LoadLibrary/GetProcAddress functions to dynamically call the functions at run-time, but would prefer to not to.)
I didn't notice anything that would tell me whether you are doing 32 or 64 bit coding. MSDN has some information on how to create an import library based on a dll that you have no source for. This article is for making a 32 bit import library. CHEERS!
I have a project that I converted from Visual Studio 2003 .NET to Visual Studio 2010. It's NOT a .NET project; it's Visual C++ (unmanaged).
The DLL pulls in additional DLLs. If I link an executable with this DLL, then the executable dies during the initialization of the DLL. (I can tell, there are constructors for static objects that are being called, and I can see their operation.) I've removed ALL VS 2010-created DLLs from my path, except for one of them, which causes the error. Replacing that one with the VS.NET-created version allows the program to run.
Since I'm not getting any useful information, I decided to write a test application that doesn't directly link to the DLL, but instead uses LoadLibrary to load the library. The idea was that I could use GetLastError() to help figure the issue with the library. No go; I get an error code -529697949, which isn't a Windows error code at all! (If I change the DLL to the VS.NET-created version, the program loads the DLL properly.)
I used the Dependency Walker (www.dependencywalker.com) to check the DLL, and it tells me that "At least one delay-load dependency module was not found," highlighting IESHIMS.DLL and WER.DLL. I am seeing no other error with that tool. Running it on the VS.NET-created DLL shows the same two warnings, so I figure this is a red herring.
static void showMessage(const wchar_t *wmsg)
{
std::wcout << wmsg << std::endl;
::MessageBox(NULL, wmsg, TEXT("Message"), MB_OK);
}
static void testLoadLibrary(const wchar_t *lib)
{
::SetLastError(0L);
::SetErrorMode(0);
std::wstringstream wss;
wss << "LoadLibrary: " << lib;
showMessage(wss.str().c_str());
HINSTANCE LoadME = ::AfxLoadLibrary(lib);
if (LoadME == NULL) {
DWORD dw = ::GetLastError();
wss << "Failed: Error code " << dw;
showMessage(wss.str().c_str());
ErrorExit(lib, dw);
} else {
wss << "LoadLibrary of " << lib << " succeeded.";
showMessage(wss.str().c_str());
::FreeLibrary(LoadME);
}
}
Finally, I ran Process Monitor (sysinternals.com) to monitor the test program, looking at all entries with Path containing the string "dll." I don't see anything particularly informative in this list--no idea why the DLL is failing to load.
If I use LoadLibraryEx with DONT_RESOLVE_DLL_REFERENCES, the library loads, so this really looks like a dependency issue, which is why I'm surprised that the dependency walker isn't being particularly helpful.
I've tried this on Windows 2008 R2 and Windows 2003; same behavior.
Any suggestions?
There is an OS tool to help diagnose problems like this. Download the SDK or DDK and use gflags.exe to set 'Show Loader Snaps' (+sls) for the process. That should reveal why the DLL load fails.
The loader snaps output will appear in the debugger output window.
Martyn
I am compiling a project into a .dll and trying to use it in another project. For most of the functions I use in this library, I get a System.AccessViolationException exception :
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at nglib.Ng_GetPoint(Void** , Int32 , Double* )
at ForwardModelingPlugin.CustomMeshVol3D.tesselate(CustomMeshVol3D* )
The lib I am using is called nglib - part of netgen, an open source mesher.
I have read a lot of related errors, but I don't understand why it is happening. And I cannot go into this library because it's unmanaged and the rest of my project is managed.
Thanks
AccessViolationException means either:
There is a bug in the library you are using, or
You are passing the library invalid arguments.