The ongoing saga about the interaction of C # with unmanaged C ++

After I hit my head against the wall both literally and metaphorically, I beg for help:

I have an unmanaged C ++ project that compiles as a DLL. Let me call it a CPP project. He currently works in an unmanaged environment. In addition, I created a WPF project, which will be called the WPF project. This project is a simple and almost empty project. It contains one window, and I want it to use the code from Project 1. For this, I created a C ++ CLR project, which will be called Interop Project, and also compiled as a DLL.

For simplicity, I will attach some basic testing code, which I worked through to the basics.

CPP Project has the following two test files:

tester.h

#pragma once extern "C" class __declspec(dllexport) NativeTester { public: void NativeTest(); }; 

tester.cpp

 #include "tester.h" void NativeTester::NativeTest() { int i = 0; } 

Interop Project has the following file:

InteropLib.h

 #pragma once #include <tester.h> using namespace System; namespace InteropLib { public ref class InteropProject { public: static void Test() { NativeTester nativeTester; nativeTester.NativeTest(); } }; } 

Finally, in the WPF project, there is one window that calls the Interop Project:

MainWindow.xaml.cs

 using System; using System.Windows; using InteropLib; namespace AppGUI { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); InteropProject.Test(); } } } 

And XAML itself has an empty window (created by default).

As soon as I try to start a WPF project, I get the following error:

System.Windows.Markup.XamlParseException: "A call to a constructor of the type" AppGUI.MainWindow "that matches the specified binding restrictions made an exception." Line number "3" and line position "9". ---> System.IO.FileNotFoundException: Failed to load file or assembly "InteropLib.dll" or one of its dependencies. The specified module was not found. in AppGUI.MainWindow..ctor ()

Interestingly, if I do not export the class from the CPP project, I do not get this error. Let's say if I change tester.h to:

 #pragma once class NativeTester { public: void NativeTest() { int i = 0; } }; 

However, in this case, I cannot use more complex classes. If I translate my implementation into a cpp file, as before, I get unresolved binding errors due to the fact that I did not export my code. The C ++ code I want to use is large and has many classes and is object oriented, so I cannot just move my entire implementation to h files.

Please help me understand this terrible mistake that I am trying to solve without success.

Thanks.

+4
source share
1 answer

From the very beginning, everything went wrong, your tester.h file is incorrect. When creating a tester project, the class must have the __declspec (dllexport) attribute. Any other project that uses the DLL should see a class with the __declspec (dllimport) attribute. Start fixing this with the macro in tester.h:

 #undef EXPORTED #ifdef BUILDING_DLL # define EXPORTED __declspec(dllexport) #else # define EXPORTED __declspec(dllimport) #endif class EXPORTED NativeTester { // etc.. }; 

And in the tester project, use C / C ++, Preprocessor, Preprocessor Definitions and add BUILDING_DLL.

Next, you need to make sure that the DLL is stored in the correct directory. This is what the exception complains about, it cannot find the DLL. The build directory for C ++ projects is Debug, but for WPF projects, it's bin \ Debug. Correct this by changing the "General + Directory Output" parameter, make it $(SolutionDir)$bin\(ConfigurationName) .

Create a C ++ project and make sure you can find the DLL in the Solution bin \ Debug directory. And make sure you also have a .lib file, you'll need it when you create the C ++ / CLI project. As an additional verification step, run Dumpbin.exe / export the foo.dll file from the Visual Studio command line and make sure that you really see that the class is exporting.

The next C ++ / CLI project, you need to change the Output Directory setting in the same way. Add the .lib file to the properties of the additional linker dependencies. You will get the linker errors you talked about if you skip this step. Create it and make sure you get the DLL again in the correct bin \ Debug directory.

Repeat these changes for the Release configuration.

Define project dependencies; WPF project depends on C ++ / CLI project. The C ++ / CLI project depends on the C ++ project. This ensures that projects are built in the correct order.

You now have a good chance to use these DLLs in your WPF project.

+3
source

Source: https://habr.com/ru/post/1435243/


All Articles