I have a dll (DLL A) built with VS2010 that uses MFC and other dlls built with VS2010.
I have another dll (DLL B) which is built with VS2008 and run on an application which is again built with VS2008. DLL A imports DLLB (with #import directive) and creates com objects. The creation of the objects itself succeeds however the application crashes somewhere. I think it crashes at the time of displaying the controls (these are just assumptions). The thing is I don`t have the source for the application. DLL A is just a plug in to that application.
The question is, is there anything to be considered when doing such mix? Is it possible at all?
Yes, it should be fine to call code across the DLL boundary if you use C linkage, ie. if the DLL boundary is using primitive C types like char* and int. If you're passing C++ references/pointers across the DLL boundary, you should really build both sides with the same compiler flags and the same compiler. There's no guarantee for example that the VS2010 compiler will layout memory for a class object in exactly the same way as the VS2008 compiler Although if you use the same byte alignment flags, the layout will most likely be the same, you can't guarantee it.
Related
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.
In my work we have VS2008.
Some partners in the project I work, use VS2010 (can't use VS2008)
They have to build a dll based and I have to use that dll in my framework...
I managed to build the main app and link the dll's.
the app starts, and objects from the VS2010 dll's are created,
but the app crashes when i try to delete these objects...
Windows has triggered a breakpoint in app.exe. This may be due to a
corruption of the heap, which indicates a bug in app.exe or any of the
DLLs it has loaded.
Have you any ideas on how to fix this?
Your co-workers' DLLs are linked against VS2010's runtime library. Your code is linked against VS2008's runtime library.
When you call some function from the VS2010 dll to allocate a new object, it will be allocated on that library's heap. When you call "delete" on that object, VS2008's runtime library will try to free it from its own heap. Since they're different, you get that error.
If you're going to mix runtimes like that, you need the VS2010 dll to expose free()-style functions (not just C++ destructors) for each type. There are other things you should be very careful with when mixing runtime libraries like that, such as using STL containers, or any sort of "copy-on-write" objects. In general, it's easier to avoid it.
Object that was allocated in dll or in an exe should be deallocated in same place. You need to talk about that with your partners. For the goal may be used overloading of allocating and deallocating operators http://www.cprogramming.com/tutorial/operator_new.html
Consider a C++ API defined as a series of __options(declexport/import) classes.
Further, assume that the caller is never permitted to call the ordinary operator new(size_t) on these classes. Either a static factory method does the new-ing or there is a class-specific operator new. And ditto marks on the delete size as needed (frequently just a virtual destructor).
Now, if you compile and link a DLL and an IMPLIB of with the tools from VS2010, can you hand that implib and DLL to a user of VS2005 and expect it to work?
MFC is not involved here at all.
I'd be particularly grateful to any reference to any relatively formal Microsoft statement on the subject.
So long as the name mangling on the C++ API is identical (they are), and does not use STL-type specific parameters, such as basic_string or std::map, whose implementation may have changed between releases of the compiler (and they have), then it should just work.
Of course, you'll want to make sure you either compiled your DLL using /MT mode (static linked runtimes), or include the redistributables for VS2010 runtimes with your supplied libraries and link targets.
EDIT: Expanding on "don't pass in types that have version-specific implementations". A partial list is most easily found by looking at the output of the exports of MSVC100P.DLL.
cd %VS100COMNTOOLS%\..\VC\redist\x86\Microsoft.VC100.CRT
DUMPBIN /exports MSVCP100.DLL
The next issue will be header-only implementations of things like map or set which have changed under the hood between versions of the compiler.
This is why it's highly recommended that only scalar types be passed across boundaries between memory arenas. And thus, simple tests will pass, and be reliable.
You have not mentioned if you have used MFC to create the DLL's .If you have, regular DLL's should work , but I dont think extension shall work as the latter links to the MFC dlls .I am including links for your reference.
http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c4017
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/Q_20385543.html
http://msdn.microsoft.com/en-us/library/26h8x9sy%28v=VS.100%29.aspx
EDIT
If its a normal DLL, there should not be any problem.Also depends on the linkage type.
I have a project written in C++/CLI. Some of the types there are in managed code, and some are in completely native code. Let's say I have the produced DLL on a machine that dosen't have any version of the .Net framework installed, is there a way that another, native application will link with my "mixed-mode" Dll and use only the native types? I've noticed that the minute I add the "/clr" switch, my Dll automatically depends on several .Net Framework Dlls (mscorjit, mscoree etc.), and when I actually try to use the 100% native types defined in it, the application still tries to load those .Net Framework Dlls (even though I don't use the framework in that part of the code).
So, is it possible to avoid loading those Dlls in such case? (as I see it, the other option is to create another, native project, that will contain all of the native types, without the managed ones).
Thanks
No. When you load a mixed mode assembly (/clr), right after DllMain runs, the .cctor runs and initializes the framework, if it hasn't already been setup for the application.
Without this, there would be a big hit as soon as you called a function that required a managed API. For details, see "Initialization of Mixed Assemblies" on MSDN.
The best option would be to make your native API a separate DLL, and have the mixed mode assembly a separate project, so you can load it separately if required.
Is it possible to use a C++ static library (.lib) compiled using Visual Studio 6 in Visual Studio 2008?
It really depends. Does the lib expose only 'extern "C"' functions where memory is either managed by straight Win32 methods (CoTaskMemAlloc, etc) or the caller never frees memory allocated by the callee or vice-versa? Do you only rely on basic libraries that haven't changed much since VS 6? If so, you should be fine.
There are 2 basic things to watch for. Changes to global variables used by 3rd-party libraries, and changes to the structure of structs, classes, etc defined by those 3rd-party libraries. For example, the CRT memory allocator has probably changed its hidden allocation management structures between the 2 versions, so having one version of the library allocate a piece of memory and having another free it will probably cause a crash.
As another example, if you expose C++ classes through the interface and they rely on MS runtime libraries like MFC, there's a chance that the class layout has changed between VS 6 and VS 2008. That means that accessing a member/field on the class could go to the wrong thing and cause unpredictable results. You're probably hosed if the .lib uses MFC in any capacity. MFC defines and internally uses tons of globals, and any access to MFC globals by the operations in the .lib could cause failures if the MFC infrastructure has changed in the hosting environment (it has changed a lot since VS 6, BTW).
I haven't explored exactly what changes were made in the MFC headers, but I've seen unpredictable behavior between MFC/ATL-based class binaries compiled in different VS versions.
On top of those issues, there's a risk for functions like strtok() that rely on static global variables defined in the run-time libraries. I'm not sure, but I'm concerned those static variables may not get initialized properly if you use a client expecting the single-threaded CRT on a thread created on the multi-threaded CRT. Look at the documentation for _beginthread() for more info.
I shouldn't think why not - as long as you keep the usual CRT memory boundaries (ie if you allocate memory inside a library function, always free it from inside the library - by calling a function in the lib to do the freeing).
this approach works fine for dlls compiled with all kinds of compilers, statically linked libs should be ok too.
Yes. There should be no issues with this at all. As gbjbaanb mentioned, you need to mind your memory, but VS2008 will still work with it. As long as you are not trying to mix CLR, (managed) code with it. I'd recommend against that if at all possible. But, if you are talking about raw C or C++ code, sure, it'll work.
What exactly are you planning on using? (What is in this library?) Have you tried it already, but are having issues, or are you just checking before you waste a bunch of time trying to get something to work that just wont?
Sure it'll work.
Are you asking where in VS2008 to code the references?
If so, go to proj props -> Linker -> Input on Configuration properties on the property pages. Look for "additional dependencies" and code the .LIB there.
Go to proj props -> Linker -> General and code the libs path in "Additional Library Directories".
That should do it!!
There are cases were the answer is no, when we moved from VS6 to VS2k5 we had to rebuild all our libraries, as the memory model had changed, and the CRT functions where different.
There were a handful of breaking changes between VC6, VS2003, VS2005 and VS2008. Visual C++ (in VS2005) stopped support for single-threaded, statically linked CRT library. Some breaking changes enumerated here and here. Those changes will impact your use of VC6 built libs in later versions.