Regarding linking a c++/cli dll and a c++/cli exe project - visual-studio

I have a native c++ dll called native.dll.
I have created a c++/cli project called cliWrapper.dll. In this I have two wrapper classes for some classes in native.dll.
And the compilation for this project works fine.
However, when I try to link cliWrapper.dll with my c++/cli console program, the linker complains that I must compile cliWrapper.dll with the compiler option /clr:safe.
Compiling with such option will generate lots of errors since most of native.dll is not verifiable code.
After googling, I see that linking two .module files requires each is compiled with /clr:safe.
Does that mean it is impossible to make a dll that will allow the user to use the wrapper class to do some stuff? I know I can always put those wrapper classes back into the console project and it will compile without problem but I'm just curious about why Microsoft wants to disable such linking?

Related

Do you need dllexport macro for every single function in your library in visual studio?

I am new to Visual Studio, so if I say something wrong, please point me to the right direction.
I have a large C++ project that consists of shared library of around 20 classes and 7 executables, built by CMake in Linux. Each executable has its own CMake setup that links against the library.
I watched couple of videos on VS, managed to understand how to structure code and dependent libraries and successfully compiled the library statically.
I even managed to setup CMake in Visual studio, but started receiving an error that my .dll file is not Win32 application when I tried to build a project that links to it, so I dropped CMake and built the library by first making empty project and then adding necessary files (I thought it's CMake issue).
Long story short, now I have new setup for my library in VS that builds without issues. However I want my library to be dynamic because it makes ton of sense as 7 different projects depend on it and that's how I did it in Linux.
To my big surprise, even though selecting .dll will build, it cannot be linked to (I started all of this as empty project, not .dll template).
What I just discovered that building .dll library requires a macro that looks like (taken from https://learn.microsoft.com/en-us/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=msvc-170):
#ifdef MATHLIBRARY_EXPORTS
#define MATHLIBRARY_API __declspec(dllexport)
#else
#define MATHLIBRARY_API __declspec(dllimport)
#endif
and before return type of any function in library I need to add the macro as:
MATHLIBRARY_API double some_function();
So if I understand correctly, this macro is "exporting" function names to .dll. Does that then mean that I need to open all 20 header files and wrap every single function in it with the macro?
Note that most header files are class declarations, do I need to wrap every single class method, just the public methods and is there a way to make a whole class "exported"?
It seems quite a cumbersome task just to build a shared library. I realize now this is why cmake failed and kinda begs the question on its cross platform capabilities if this wrapping to make .dll in VS needs to be done like this.
I am considering building my library statically, and in the same solution, add additional projects, and make a reference to the static library.
It kills modularity of the project, but it should work fine.

No_CLR_Support C++ project with a C++/CLI source file

We have a VS2010 C++ project with No Common Language Runtime Support set in its project properties. Then I see that it has a source file containing some managed code and the properties for this file has "/clr" flag set. So the project does not have a /clr flag but a file inside it has. I am confused as to whether it makes the project a mixed mode one? I can open the output file in ILDisassembler which makes me believe that it indeed is a .NET assembly.
This is entirely normal, a C++/CLI project very commonly contains a mix of native C++ and C++/CLI source code files. The setting in the General setting pages merely sets the default that the compiler will assume. But turning it on for each individual source file is quite valid and common.
Other ways to do this is to keep the native C++ code in a separate library project and link it. Or by turning on MSIL code generation on and off on-the-fly in a single source code file by using #pragma managed.
The linker doesn't have to be told about it, it can tell from the content of the object file. And yes, you will get a mixed-mode .NET assembly. With the C++/CLI bits compiled to MSIL and the native C++ code compiled to machine code.

C++/CLI wrapper for C++ native dlls

I have native C++ dlls that I need to use in our group's new C# programs. I wanna create C++/CLI wrappers for native C++ dlls, so as to be able to import and compile them in C#.
What I need to know is how to load the dll file in the wrapper source file at the first place. Exactly the same thing that #using <...> does for MSIL, but for loading native C++ dlls.
And also, how will the objects and namespaces inside the dll become accessible then (synatically)?
EDIT:
I use
class __declspec(dllexport) radar
{
// declarations and definitions
...
};
to export my radar class from my radar.dll, and need to import it in a VC++(CLI) program like this: __declspec(dllimport) public class radar; so as to conduct it's definition into C#, but definitely I can't see radar in C#, because its not defined public in VC++(CLI). Even when I wanna use native dll's objects in VC++ dll's code, like radar pos1(); I get:
error C2512: 'radar' : no appropriate default constructor available
How can do this, having just the radar declaration at hand?
END EDIT.
Thank you!
It is automatic, you don't do this yourself. You specify the native DLL import libraries (.lib) in the linker settings for the C++/CLI project, Additional Dependencies setting. The linker links in a reference to the DLL name into the C++/CLI assembly. As soon as the C# code uses any of the managed types in the C++/CLI assembly, the CLR loads the assembly. Windows notices the native DLL references in the DLL and automatically loads them.
This can only come to a good end if Windows can actually find the native DLLs at runtime. Copy them into the build folder of the EXE project. That's awkward, you can do it with a post-build event or by adding them to the C# project with their Copy to Output Directory property set to true.

How to properly build third-party library to be used in Debug and Release configurations in my project?

When I need to build some third party library to be used in several of my projects under different version of MSVC, I usually build it for every MSVC version and for both Debug and Release configurations. That's what boost does, and that's what we have been done for our whole life in my team.
However, I still don't get, why couldn't I just build this library with like... whatever. All I need is function prototype and object code, right? Since I'm linking CRT statically, I have no external dependencies. But when I'm trying to link library built in Release under MSVC8 with my project in Debug under MSVC10 I have this annoying "already defined" linker errors which we all hate so much.
But why? Can I just "encapsulate" all this functions inside lib and do not export them so that my project will take only what it needs from the lib? Why can I have precompiled version of libpng and zlib which I can link in every project? Yes, they are not build using MSVC, I guess, but the still uses the same functions of CRT. So can anyone please explain in depth or share a link to some enlightened explanation of this issue?
Since I'm linking CRT statically, I have no external dependencies
Well, that's not true, you do have a dependency. On the static version of the CRT. Debug or Release, depending on your build settings. And it is an external dependency, the linker glues the CRT later, when the library gets linked. The code that uses the library also has a dependency on the CRT. And if the compile settings don't match then the linker barfs.
You isolate that dependency by building a DLL instead of a static link library. You must further ensure that the exported functions don't cause a CRT dependency. You can't return a C++ object from the standard C++ library and can't return a pointer to an object that needs to be released by the client code. Even passing structures is tricky since their packing is an implementation detail, but you usually get away with it. A good practical example is COM automation, it forces you into using a subset of types that are universal. Windows is rife with them and all these servers work with any version of the compiler or CRT. Even any language. This however comes at a cost, writing such a library isn't as simple or convenient as just throwing a bunch of code in a static lib.

Using /clr and noclr libraries in one project

I am encountering some issues with one project. I need to use two libraries but one needs to be compiled with the /clr switch as the other cannot be compiled with this switch.
Would there be a way to use at the same time those two libraries in one project? Currently it's compiled with /clr and I got linking errors with the noclr library.
If there is no solution I can still launch the noclr library in batchmode but I'd like to avoid it...
My project is in Managed C++, the library tetgen - which needs /clr - is in native C++ and cannot be compiled without the /clr switch, as I get this error
error C3381: 'tetgenio' : assembly access specifiers are only available in code compiled with a /clr option
The other library triangle is in C. I am on Visual Studio 2008 and the project is compiled in 32 bits.
We could use more details, but using managed C++ you can certainly use a mix of managed and unmanaged code. (Microsoft calls their managed c++ code C++/CLI.)
EDIT:
Ok, your compiler error helped. Apparently you have specified a native class, but using public private, or some other access specifier on the name of the native class. From the MSDN docs:
The following sample generates C3381:
// C3381.cpp
**public** class A { // C3381. Remove public or make the class
managed. };
int main() { }
so get rid of the public keyword, and then try compiling again.
You can have multiple projects in a single solution. Right click on the solution in the eolution explorer and add -> existing/new project. Each library project can be added that way and have their own clr settings.

Resources