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
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)
Recently upgraded to a new PC with Win 10 pro, Excel 2016 coming with Office365, vs2015 community. Built a very simple vc++ dll with just one function exported in def file. The code is very simple but would still post here to give a content and make sure there's no problem there.
//also tried __declspec(dllexport) double sumCPP(double a, double b) without .def file
double __stdcall sumCPP(double a, double b)
{
return a + b;
}
'VBA
Public Declare PtrSafe Function sumCpp Lib "C:\MyTestProject\x64\Debug\DllTest.dll" (ByVal a As Double, ByVal b As Double) As Double
But a call from VBA results Run-time error '48': File not found: C:\MyTestProject\x64\Debug\DllTest.dll.
The source code of a more complicated dll project can be built to exe that runs fine, but whose dll prompted this original failure calling dll problem. Any suggestion where to look at? I've tried depends.exe with many supposedly false alarms and dumpbin /dependents but not clear how to use the result. I wonder if this is related to some vs2015 redistributable not in system PATH. I don't see any there but haven't tried to add them yet, as there seem to be too many.
Is there any other option to delegate heavy computation and TCP/IP socket besides using vc++ dll? I don't know but can consider C#, while python would be preferred. Since those dll functions are intended to be called many times in VBA, a system call to vc++ exe doesn't seem to be efficient.
Great thanks in advance!
Since the machine is new so I reset it removing all data. Then I installed Office 2016 64bit and VS Community 2015 from scratch and built the 64bit dll again. This time the error is Run-time error '453' Can't find DLL entry point. Can't find any obvious missing dependent dll by either dumpbin.exe /dependents or depends.exe.
Try change build configuration from "Debug" to "Release"
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.
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'm new to vc++. I've just built a software and it generated a .dll and a .lib. I need to use functions from this in my code. Do I need to link to both .lib and .dll to build my code? What project properties do I have to alter to do this linking?
Actually, you need only the .dll file. It contains all the necessary code and data to run it's functions. It also contains a table that links the symbolic names of the functions (e.g. the function PrintMe), their ordinals (the number of that function in the DLL) and their addresses in the DLL.
If you want to use only the DLL, you have to "manually" get the symbols resolved:
Let's say you want to use the function PrintMe of the DLL. What you had to do is to resolve it's name (PrintMe) or it's ordinal (PrintMe is the 1st function of the DLL) to it's address. For this, you could use LoadLibrary, GetModuleHandle and GetProcAdress from the Win32 API (aka Windows SDK). Additionally, this method allows you to load the DLL at runtime (see below).
The easier way is to use the MSVC(++) features __declspec(dllexport) and __declspec(dllimport), e.g.
// your DLL
__declspec(dllexport) void PrintMe()
{
printf("Hello World!");
}
// you project to use the DLL
__declspec(dllimport) void PrintMe();
The first one (dllexport) tells the compiler to export the function. The second one (dllimport) is the interesting one: It creates all the necessary code to be able to use the function from the DLL.
For this, you need the .lib file in your project (which wants to use the DLL). The .lib file contains information for the linker to resolve the symbol name (PrintMe) to its address in the DLL. Since the .lib is statically bound, the linker can make use of it - the DLL on the contrary is bound at runtime / loading time, so the linker cannot use it. (Yes, the information in the .lib file is redundant.). Note: You cannot change the whole DLL when using this method w/o rebuilding your project with the new .lib file. Some structure changes affect the addresses of the functions in the DLL, see this SO answer.
One last difference between using the Win32 API (LoadLibrary...) and the MSVC method via __declspec is the loading of the DLL. When you use LoadLibrary, the DLL is loaded at runtime, of course (so you can catch exceptions when it cannot be found and so on). The other method loads the DLL at loading time, so you program will terminate (will not run) when Windows cannot find the DLL.
When you create a project in VS, you can activate the "export symbols" checkbox at the end of a wizard (Win32 project). That gives you some examples of exported symbols. Additionally, it introduces a macro plus a preprocessor defition plus some directives that are very useful:
// DLL header
#ifdef _YOUR_DLL_EXPORTS
#define YOUR_DLL_API __declspec(dllexport)
#else
#define YOUR_DLL_API __declspec(dllimport)
#endif
YOUR_DLL_API PrintMe();
You now can use this header file to build you DLL as your DLL project has that _YOUR_DLL_EXPORTS definition (see project properties page, C++, preprocessor). The project that uses the DLL can use this header, too, but then must not have such a name defined. When you include the header file in the project in which you want to use the DLL, the macro is resolved to __declspec(dllimport). This instructs the linker to look for this function (which is found in the .lib file) and create all the necessary code to load the DLL at runtime and resolve the symbol name.