How to call unmanaged code in a DLL from managed code

Source: Internet
Author: User
Tags dotnet

Recently internship in the company received a new project requirements, generally speaking, the need to implement C + + and C # language interoperability. Sounds a bit abstract, in fact, is able to use C + + code calls. NET platform FCL, and C # code can, in turn, invoke functions in a DLL that is written by C + +.


C + + calls Dotnet base Class library is easy, after all, the Dotnet platform is designed to achieve the language independant goal, it through the c++/cli for the traditional C + + language can work under a new platform to provide strong support. We just need to change the syntax of the code a little bit, and then manually package the function into a wrapper to work under the Dotnet platform. This article focuses on how to invoke an unmanaged DLL from a managed C # module.


Because the DLL file already exists, the cost of overwriting it with C++/CLI is quite large. Furthermore, if the DLL is a commercial product provided by a third party, we cannot and will not be allowed to modify its source code. So here we have to use the platform Invoke services provided by the Dotnet platform to achieve our goal. There are a lot of examples of how to use PInvoke on the Web, and MSDN has a detailed description, but I still have a bit of a problem when I try.


The following is a standard C-style DLL header file, which we name as MyLib.h

#ifdef mylib #else #define mylib extern "C" _declspec (dllexport) #endif mylib double Add (double A, double);

The file declares an add function that implements the addition of two floating-point numbers. Its corresponding implementation file MyLib.cpp is very simple,

#include "myLib.h" double Add (double A, double b) {return a + B;}

With Visual Studio compiling the dynamic link library project, the debug directory generates two important files, one of which is MyLib.dll, and the other is a file called MyLib.lib. MyLib.dll is the dynamic link library We're going to call, so what's the. lib suffix? What else does it need to do with a DLL? Don't worry, I'll talk about it later:

Next, create a C # Console application project to reference the compiled MyLib.dll.

Using System; Using System.Runtime.InteropServices; Class Platforminvoketest {[DllImport ("MyLib.dll")] public static extern double Add (double A, double b); public static Voi D Main () {Console.WriteLine (Add (2d, 3d));}

In order to be able to use the DllImport property, it is necessary to reference the System.Runtime.InteropServices namespace. The DllImport property is actually the DllImportAttribute class, where we can specify the field value of the class when we actually need it, in this case we only specify the name of the DLL file that needs to be referenced. In addition, the field that is usually required to be described also has Entrypoint,charset and callingconvention, and if not explicitly stated, the system will take the default value, and the above example will use the defaults. DllImport can refer to the MSDN related section:

Http://msdn.microsoft.com/en-us/library/e4takf5s%28v=VS.71%29.aspx

It is important to note that DllImport is only effective once, and it acts on the method immediately following it. That is, if there are multiple functions that need to be declared, we must reassign the DllImport attribute once before the beginning of each function. Only the Add function is referenced here, so there is no such problem. After the DllImport attribute, we declare the Add function to be referenced, and extern hints to the compiler that the definition of add needs to be found elsewhere.

Finally compile the test file, the debug directory to generate EXE executable file, note that this time we have not just generated the MyLib.dll copy to the debug directory. Running the generated EXE, as we expected, the program throws a Run-time exception system.dllnotfoundexception. Obviously, the reason is that the system is unable to locate the dynamic link library MyLib.dll. As a remedy, we'll copy the file to the debug directory and re-run the EXE, which is always the right time.

Oppps, the program again crash dropped, this time throws another unusual system.badimageformatexception. To be sure, the system has found the MyLib.dll file, otherwise the runtime will complain that the DLL could not be found, so what does this file image damage mean.

The first I can think of is only the DLL file problem. To confirm that, I wrote a simple C + + program to invoke MyLib.dll, and found that it can run normally. Go back to the test files of C # again, seemingly no error, the MSDN example is also written. So depressed, exactly where the problem caused the DLL can not be called normally. Toss a morning, suddenly think of Windows via C + + A passage in the book about DLLs, as the book says--

A DLL can export variables, functions, or C + + classes to the other modules. Should avoid exporting variables because this removes a level of abstraction in your code and makes it m Ore difficult to maintain your DLL ' s code. In addition, C + + classes can be exported only if the modules importing the C + + class are compiled using a compiler from th E same vendor. For this reason, you should also avoid exporting C + + classes unless you know the executable module developers use the Same tools as the DLL module developers.

The emphasis is on the opening sentence in addition, simple but not accurate: to make the exported C + + class module available, the import module must be compiled with the same manufacturer's compiler. I don't know the reason for this limitation, but I have some clue. Here my DLL and test files are developed in the Win7 + Visual Stuidio Environment, the book says the potential problem is not tenable to me, but I have begun to suspect that the problem is a compilation of the trouble. So the Internet search keyword, c#,dll,badimage, suddenly flashed 32bit,64bit words, let me suddenly wake up, I immediately feel the problem will be solved.

The target platform for C # test files is anycpu, which means that the generated EXE has the intelligence to operate 32bit on the 32bit machine and to operate 64bit on 64bit machines. I use the machine is 64bit, so good, exe in the default 64bit to run the way on my machine. We know that once a program starts running in 32bit or 64bit, it is 32bit or 64bit until its lifecycle is complete, and other dependent modules it loads are the corresponding versions. In other words, a 32bit applicaition cannot load a 64bit version of a dependent module (such as a DLL), or vice versa. Looking back at my DLL project, target platform is x86, which is compiled with a 32bit version. On the other hand, because the C # test file is anycpu, the EXE will run 64bit on my 64bit machine, and it will try to load the 64bit DLL when it runs, and the DLL we just generated is 32bit, and of course it complains that the file image is corrupted. The problem was pulled out by a conscientious effort.

Because unmanaged code must be targeted at a particular platform, it is not possible to compile with the ANYCPU option, either by selecting x86 or by x64. There are two ways to solve the problem here: DLLs are compiled with 32bit, C # is compiled with x86, DLLs are compiled with x64, and C # can be compiled on 64bit machines anycpu or x64. Try to run it, and the program works perfectly. It's a long time to blame the evil 64bit operating system. This problem is not possible on the ~32bit machine, so many people can replicate the MSDN example directly, so the problem is being completely ignored.

The

Now goes back to the Lib file that was generated with the DLL that you just talked about. In fact, if you use C + + to invoke a DLL written by C/s + +, Lib is essential when the chain is delivered into an EXE executable. A Lib file is a list that lists the names of all the DLL modules referenced in the EXE, along with all the exported symbols in each DLL file. It needs to be described, just the name, and no other collateral information. In the link phase, the linker checks against the Lib list to ensure that the DLLs can be found, and that the name references do exist, otherwise the link goes wrong. Once successful through the link, Lib file is useless, load the runtime system no longer has the operation for LIB, so after the generation of EXE file we will remove the Lib from the folder does not affect the normal execution of the program, but the DLL is dynamic loading, It is natural to put it in a specific folder to ensure that it can be found by the system anytime. But interestingly, dotnet platform we do not need lib file can be normal generation of EXE, look back at the above process, we useful to Lib file. This may be related to the special working mode of the Dotnet platform, which needs further study in the future.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.