I have a dll in my c++ program and I want to rewrite it myself and replace it out.
The dll I am replacing has 3 classes. I want to replace each class one by one with my new dll, but I do not want to change any of the other code.
To do this I was going to use the same class names in the new dll as in the old one.
However I would like to replace one class, run my program then replace the next class etc so I do not have to try and change everything at once to make sure stuff is working.
Is there a way to do this? I assume if both dlls are included the namespaces will conflict
I am not sure of what you are trying to do but something such as what Neil indicates might work well enough. It might work to have different namespace names and then just rename the newer namespace to the production name when you are ready to eliminate the old one.
When linking, it is possible to specify multiple lib files. I know that the order of the lib files can determine which is used. I forget if that can be used for this, but perhaps you can specify multiple lib files with the same classes and functions and the linker will use the DLL for the first lib file it finds for the class. I forget the details of how that can work.
Related
I am trying to write my first (very) small, for now only self-use, library. In the process I came across questions regarding how I should separate my headers/source code/object files in a logical way.
To be more specific, I'm writing a small templated container class, so for one I have to include the implementation of this class inside its header.
I have a directory structure like this:
include/ - "public" .hh header files included by extern projects
src/ - .cc files for implementation (+ "private" .hh header files?)
lib/ - .o compiled library files linked by extern projects
I am already not sure if this makes sense.. in my case I also wrote some helper-classes used by my templated container class, one of which is something like an iterator. So I have the following files:
container.hh
container.cc
container_helper.hh
container_helper.cc
container_iterator.cc
container_iterator.hh
While I want to have access to their functions in external projects (e.g. incrementing the iterator), it makes no sense to me that a project would specifically
#include "container_iterator.hh"
Now, since I want projects to be able to use the container class, I put "container.hh" and "container.cc" (since it must be included in "container.hh" because of the template) into the "include/" directory, which is then included by other projects.
Now my confusion arises.. the container class needs access to the helper classes, but I don't want other projects to only include the helper classes, so it seems wrong to place also the helper classes into "include/" directory. Instead, I would place them in "src/".
But if I do this, then to include these in "include/container.cc" I have to use relative filepath
#include "../src/container_iterator.hh"
But now if I "distribute" my library to an external project, i.e. I only make the "include/" directory visible to the compiler, it will not compile (?), since "../src/container_iterator.hh" does not exist.
Or do I compile the container class and put it as library into "lib/", which is then linked by other projects? But even then do I not still need to include the header "container.hh", to be able to find the function declarations, which leads to the same problem?
Basically I'm lost here.. how does the standard do this? E.g. I can
#include <vector>
, but I don't know of any header to only include std::vector::iterator, which would make no sense to do so.
At some point in my expanation I must be talking nonsense but I cannot find where. I think I understand what a header and a library is/should be, but when it comes to how to design and/or "distribute" them for an actual project, I am stuck. I keep coming across problems like this even when I started learning C++ (or any language for that matter), no course / no book ever seems to explain how to implement all these concepts, only how to use them when they already exist..
Edit
To clarify my confusion (?) more.. (this got a bit too long for a comment) I did read before to put implementation of templated classes into the header, which is why I realized I need to at least put the "container.cc" into the include/ dir. While I don't particularly like this, at least it should be clear to an external user to not include ".cc" files.
Should I take this also as meaning that it never makes sense to compile templated classes into a library, since all of it will be always included?
(So templated code is always open-source? ..that sounds wrong?)
And in this case I still wonder how STL does it, does vector declare & define its iterator in its own header? Or is there a separate header for vector::iterator I could include, it just would make no sense to do so?
Hopefully I explained my intent clearly, please comment if not.
Thanks for any help!
In my experience, the most common method to handle your problems is to have headers with the template declarations and documentation (your .hh files), which also include .inc or .tcc (your preference) files with the template definitions. I also suggest keeping all files that may be included by external projects in the same folder, but if you want to keep things clean, put your .inc/.tcc files in a folder within include called detail (or bits if you like GNU style).
Putting stuff in a detail folder,
and using a weird extension should deter users enough.
To answer your other questions:
Due to the nature of C++ templates,
either the entire source of the parts of a template you use
must be present in the translation unit (ie. #include'd),
or you can use explicit instantiation
for a finite number of arguments
(this is not generally useful for a container, though).
So, for most purposes, you have to distribute a template's source, though,
of course, (as mentioned in the comments) "open source" is about licence,
not source visibility.
As for the standard libraries, lets use <vector> as an example.
The GNU C++ Library has a vector file that (among other things) includes
bits/stl_vector.h which has the declarations & documentation,
and includes a bits/vector.tcc that has the definitions.
LLVM's libc++ just has one giant file,
but puts the declarations at the top (without documentation!)
and all the definitions at the bottom.
As a final note, there are lots of open source C++ libraries that you can take a look at for inspiration in the future!
I have some beginner's question regarding c++.
I've downloaded windows SDK and according to the documentation, all bluetooth traffic uses winsock. Windows SDK includes header files (.h) if I want to program a bluetooth interface.
a) This is a general c++ question: how does the header file winsock.h gets linked to a specific dll? I didn't specify any link. How can I detect all the .dll that are linked with this header?
Isn't the header file suppose to contain only the names of the functions and the actual implementation in the dll? I'm slightly confused.
My second goal is to replace the windows winsock functions by a modified version. I would like to keep the original functionality, unless some flag, set by a different application, is set to true. In this case, I want to modify some functions.
My approach is to create a new dll, that will have the same function names, as shown in the header file winsock.h .
b) Assume that there exists a function fff in the original winsock. I'll replace it with a new function, that unless the flag is true, calls the same function fff but in the unmodified dll, i.e.. I want in this case to "include" the original function from the unmodified dll and "overload" my modified fff function, with the original fff function. This two functions have the same parameters, and the same name. How do I that? Is there a better way to achieve the same goal?
c) what is the best way (or the easy way) to allow the flag, set by an application, to be accessible within the dll?
d) Winsocket is a very central component. Should I expect a major performance deterioration if I add one if command to every function in it?
Thanks!
a) The header file simply defines things (types, functions, classes) that are to be found elsewhere - it does not specify where. When you link the program you include .lib files which contain (among other things) the connection to the correct DLL. When the program runs the lib code will load the DLL into memory and connect to it.
b) Generate a second DLL that contains all the same functions as in winsock but with (say) ELI_ added to the start of the function name. Then inside the ELI_ function look at the flag and if it's not set call the basic winsock function, otherwise do whatever special thing you have in mind.
c) Make the flag variable a global static variable within your ELI_ DLL code, then add extra functions to set the flag (and read back its state, probably)
d) I don't know, but a single if is not going to take very much time at all. I would be more worried about what your special code does.
I have written a system that registers metadata for a class when initiating a static bool.
For example :
bool CreateMetaDataForTestClass() {
// Registration of metadata
}
static bool initBoolForTestClass = CreateMetaDataForTestClass();
The system works great.
There is a problem, however. I can create classes using strings from config files. If I have a situation where a class I want to use is never included in any files, the compiler seems to ignore the files, and consequently NOT initiate my static variable and not register my class.
If I'm lucky - Is there a compiler switch that solves this problem?
I would like to NOT have to include those files, as it is kind of the point of the system - to have zero integration with the engine as the class registers itself automatically.
At some point you need to tell the system which classes are available. If you want to have a statically linked executable, you will have to specify all object files linked into the executable. When you want to specify the available classes only at run time you will need to provide some sort of configuration (e.g. by searching a particular directory or a file listing the objects) for shared objects your program needs to load. It won't just be magically there.
You'll need a makefile project.
http://msdn.microsoft.com/en-us/library/txcwa2xx%28v=vs.80%29.aspx
I am currently working on a project that has a number of COM objects written in C++ with ATL.
Currently, they are all defined in .cpp and .idl files that are directly compiled into the COM DLL.
To allow unit tests to be written easier, I am planning on moving the implementation of the COM objects out into a separate static library. That library can then be linked in to the main DLL, and the separate unit test project.
I am assuming that there's nothing particularly special about the code generated by ATL, and that this will work much like all other C++ code when it comes to linking with static libraries. However, I don't have too much actual knowledge of ATL myself so don't know if this is really the case.
Will this work as I'm expecting? Or are there pitfalls that I should look out for?
There are gotchas since LIBs are pulled in only if they are referenced, as opposed to OBJs which are explicitly included.
Larry Osterman discussed some of the subtleties a few years ago:
When I moved my code into a library, what happened to my ATL COM
objects?
A caveat: This post discusses details of how ATL7 works. For other
version of ATL, YMMV. The general principals apply for all
versions, but the details are likely to be different.
My group’s recently been working on reducing the number of DLLs
that make up the feature we’re working on (going from somewhere
around 8 to 4). As a part of this, I’ve spent the past couple of
weeks consolidating a bunch of ATL COM DLL’s.
To do this, I first changed the DLLs to build libraries, and then
linked the libraries together with a dummy DllInit routine (which
basically just called CComDllModule::DllInit()) to make the DLL.
So far so good. Everything linked, and I got ready to test the new
DLL.
For some reason, when I attempted to register the DLL, the
registration didn’t actually register the COM objects. At that
point, I started kicking my self for forgetting one of the
fundamental differences between linking objects together to make an
executable and linking libraries together to make an executable.
To explain, I’ve got to go into a bit of how the linker works. When
you link an executable (of any kind), the linker loads all the
sections in the object files that make up the executable. For each
extdef symbol in the object files, it starts looking for a public
symbol that matches the symbol.
Once all of the symbols are matched, the linker then makes a second
pass combining all the .code sections that have identical contents
(this has the effect of collapsing template methods that expand into
the same code (this happens a lot with CComPtr)).
Then a third pass is run. The third pass discards all of the
sections that have not yet been referenced. Since the sections
aren’t referenced, they’re not going to be used in the resulting
executable, so to include them would just bloat the executable.
Ok, so why didn’t my ATL based COM objects get registered? Well,
it’s time to play detective.
Well, it turns out that you’ve got to dig a bit into the ATL code to
figure it out.
The ATL COM registration logic gets picked in the CComModule
object. Within that object, there’s a method
RegisterClassObjects, which redirects to
AtlComModuleRegisterClassObjects. This function walks a list of
_ATL_OBJMAP_ENTRY structures and calls the RegisterClassObject
on each structure. The list is retrieved from the
m_ppAutoObjMapFirst member of the CComModule (ok, it’s really a
member of the _ATL_COM_MODULE70, which is a base class for the
CComModule). So where did that field come from?
It’s initialized in the constructor of the CAtlComModule, which
gets it from the __pobjMapEntryFirst global variable. So where’s
__pobjMapEntryFirst field come from?
Well, there are actually two fields of relevance,
__pobjMapEntryFirst and __pobjMapEntryLast.
Here’s the definition for the __pobjMapEntryFirst:
__declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL;
And here’s the definition for __pobjMapEntryLast:
__declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL;
Let’s break this one down:
__declspec(selectany): __declspec(selectany) is a directive to
the linker to pick any of the similarly named items from the section
– in other words, if a __declspec(selectany) item is found
in multiple object files, just pick one, don’t complain about it
being multiply defined.
__declspec(allocate("ATL$__a")): This one’s the one that makes
the magic work. This is a declaration to the compiler, it tells the
compiler to put the variable in a section named "ATL$__a" (or
"ATL$__z").
Ok, that’s nice, but how does it work?
Well, to get my ATL based COM object declared, I included the
following line in my header file:
OBJECT_ENTRY_AUTO(<my classid>, <my class>)
OBJECT_ENTRY_AUTO expands into:
#define OBJECT_ENTRY_AUTO(clsid, class) \
__declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_##class = {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }; \
extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany) ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_##class = &__objMap_##class; \
OBJECT_ENTRY_PRAGMA(class)
Notice the declaration of __pobjMap_##class above – there’s
that declspec(allocate("ATL$__m")) thingy again. And that’s where
the magic lies. When the linker’s laying out the code, it sorts
these sections alphabetically – so variables in the ATL$__a
section will occur before the variables in the ATL$__z section.
So what’s happening under the covers is that ATL’s asking the linker
to place all the __pobjMap_<class name> variables in the
executable between __pobjMapEntryFirst and __pobjMapEntryLast.
And that’s the crux of the problem. Remember my comment above about
how the linker works resolving symbols? It first loads all the items
(code and data) from the OBJ files passed in, and resolves all the
external definitions for them. But none of the files in the wrapper
directory (which are the ones that are explicitly linked) reference
any of the code in the DLL (remember, the wrapper doesn’t do much more
than simply calling into ATL’s wrapper functions – it doesn’t
reference any of the code in the other files.
So how did I fix the problem? Simple. I knew that as soon as the
linker pulled in the module that contained my COM class definition,
it'd start resolving all the items in that module. Including the
__objMap_<class>, which would then be added in the right location so that ATL would be able to pick it up. I put a dummy function call
called ForceLoad<MyClass> inside the module in the library, and
then added a function called CallForceLoad<MyClass> to my DLL
entry point file (note: I just added the function – I didn’t
call it from any code).
And voila, the code was loaded, and the class factories for my COM
objects were now auto-registered.
What was even cooler about this was that since no live code called
the two dummy functions that were used to pull in the library, pass
three of the linker discarded the code!
On certain error cases ATL invokes AtlThrow() which is implemented as ATL::AtlThrowImpl() which in turn throws CAtlException. The latter is not very good - CAtlException is not even derived from std::exception and also we use our own exceptions hierarchy and now we will have to catch CAtlException separately here and there which is lots of extra code and error-prone.
Looks like it is possible to replace ATL::AtlThrowImpl() with my own handler - define _ATL_CUSTOM_THROW and define AtlThrow() to be the custom handler before including atlbase.h - and ATL will call the custom handler.
Not so easy. Some of ATL code is not in sources - it comes compiled as a library - either static or dynamic. We use the static - atls.lib. And... it is compiled in such way that it has ATL::ThrowImpl() inside and some code calling it. I used a static analysis tool - it clearly shows that there're paths on which the old default handler is called.
To ensure I even tried to "reimplement" ATL::AtlThrowImpl() in my code. Now the linker says it sees two declarations of ATL::AtlThrowImpl() which I suppose confirms that there's another implementation that can be called by some code.
How can I handle this? How do I replace the default handler completely and ensure that the default handler is never called?
I encountered similar problems when writing my own memory manager and wanted to overrule malloc and free.
The problem is that ATL::AtlThrowImpl is probably part of a source file that also includes other files that are really needed.
If the linker sees a reference to a function in one of the object files, it pulls in the object file with that function, including all other functions in that same object file.
The solution is to look up in the ATL sources where ATL::AtlThrowImpl is defined and see if the source contains other functions. You will also need to implement the other functions to prevent the linker from having any reference to the original ATL source.
I have not worked these windows libraries in quite a while, but you should be able to get the linker to pick your replacement by putting it in a static library listed earlier in the link statement. Make sure you are using the same method signature as the original. You can also play with linker flags to omit default libraries, for various definitions of default.
If you have a friend with access to MSDN, it may have some of the ATL debug sources, which also helps.
And, as Patrick says, you need to provide a replacement for everything in the same linkage scope. Some libraries break the individual methods out into separate object files to make it easier to replace one piece. That's more common with e.g. c standard lib than for a class. If there's a lot of ATL code capable of calling their throw impl in a single object file, it may be more pain than it is worth....you may need to try catching and rethrowing as your own type.