I have many projects of which generate COM DLL's, these projects output the following:
projectname_i.h
projectname_i.c
projectname_p.c
projectname_i.tlb
Then where another project consumes this DLL it is used like so:
#import "projectname.tlb" named_guids no_namespace
I want to change this to use include instead of import.
The reason behind wanting to change from #import to #include is because I want to enable the /MP compiler switch to speed up build times.
http://msdn.microsoft.com/en-us/library/bb385193.aspx
So what I would like to know is:
Why do COM DLLs have a TLB and a H?
Which should be used and why?
What is the difference between using #include vs #import? will there be any unforeseen consequences from switching to #include?
Why do COM DLLs have a TLB and a H?
The generated _i.h file contains the declarations you wrote in the IDL file in a format that's usable by a C or c++ compiler. The .tlb file is a type library, it contains the IDL declarations in a format that's usable by any language that supports COM. It gets embedded in the COM server DLL as a resource. Whomever uses your COM server will need it. If you don't build the proxy/stub DLL then it may also be needed at runtime to marshal calls across apartments.
What is the difference between using #include vs #import?
As long as the client is written in C or C++, #including the _i.h file is enough to get the necessary declarations to use the server. Do note however that the #import directive does more, it auto-generates a .tlh and a .tli file that get #included in the client code. These files declare smart pointer types for the interfaces in the COM server, types that make it a lot easier to use the server. Open these files in a text editor to see what they contain. If your client code uses the XxxxPtr types or catches the _com_error exceptions that are auto-generated from error return codes then you are looking at a very substantial rewrite of the client code if you don't want to use the #import directive.
If the COM server is stable and its interface declarations are not going to change anymore then you could check-in the .tlh and .tli files and replace the #import by two #includes for these files. Be sure to leave a comment in the code that shows a maintainer how to re-generate the files, "never change" is an elusive goal. And, of course, this trick isn't appropriate if you try to make /MP effective, that indicates that the COM server is still changing.
Related
I have a dll file, irig106.dll, that I produced from a compile in Visual Studio 2010. (The source code is here). Notice the multitude of .h files in there; the main one is called irig106ch10.h, as far as I can tell.
I would like to import it into MATLAB via loadlibrary. I put all the .h files into their own folder, called "headers". Here's what I get:
loadlibrary('irig106.dll', 'headers\irig106ch10.h', 'addheader', 'config', 'addheader', 'stdint', 'includepath', '.\headers');
Warning: Warnings messages were produced while parsing. Check the functions you intend to use for correctness. Warning text can be viewed using:
[notfound,warnings]=loadlibrary(...)
Error using loadlibrary (line 418)
There was an error loading the library
"mydir\irig106.dll"
mydir\irig106.dll
is not a valid Win32 application.
So I'm not sure of a few things:
Why is loadlibrary claiming that the dll is not a valid Win32 application? It looks like based on my Visual Studio settings, I am compiling for Win32.
Per the loadlibrary documentation, I need to explicitly use addheader for each header file I want to include, and those headers need to be #included in the base header file. In this case, I only include config.h and stdint.h in irig106ch10.h but I'd like to use all those other headers. Do I need to make a "header header" file where I include everything?
I guess I'm looking for a tutorial on how to use loadlibrary for complicated dlls with multiple headers like this, because there really isn't much in the way of examples on the internet. I'd love to see someone build the .dll (uncomment the #define IRIG_NETWORKING in config.h) and give a step-by-step.
In Xcode, I've created a "Cocoa application" project. One of its dependencies is a framework containing C++ code. I renamed AppDelegate.m to AppDelegate.mm and included the framework.
The project fails to compile. The problem is that the C++ header files in the framework are using some symbols that conflict with Objective-C or Cocoa.
The C++ header files are defining functions called verify() and check(), which conflict with /usr/include/AssertMacros.h in the MacOSX10.8 SDK.
The C++ header files contain a variable called NO, which conflicts with the Objective-C macro NO.
A workaround would be to modify the C++ code in the framework to avoid these conflicts. But since it's a large C++ project maintained by another organization, this would take time and would possibly break in future updates of the C++ project.
Is there some way just to tell Clang/Xcode to treat those C++ header files as C++ instead of Objective-C++?
Reading through the /usr/include/AssertMacros.h that comes with Mac OS 10.8, it looks like you could do:
#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
before including AssertMacros.h, which will prevent it from defining macros called verify() and check().
Regarding NO: you could use the preprocessor to rename that variable for you. For example:
#define NO NO_libraryname_renamed
#include <libraryname.hh>
#undef NO
Depending on how the NO variable is used by the library, this might cause problems — if the header is declaring it as extern, then your Cocoa app will refer to it by the wrong name, and you'll get an undefined symbol error. But as long as you're not using that variable, and the library isn't depending on your app to define that variable, then you should be fine.
(And please file a bug report with the offending library, requesting that they rename their variable.)
Mixing several languages is calling for grief. Even more so mixing Objective C++ (itself a strange hybrid) with C++. Don't do it.
I am giving Gwan a whirl.
Having made it through example code, I started a small project with more than one source file. I now have two problems:
I got a linking error at server startup:
Linking main.cpp: undefined symbol: _ZN7GwanUrl9concatAllEv
(the main file #includes the two other files; all the files are in the csp directory)
As an alternative to having all the files in the /csp directory, I would like to make a library outside of the /csp directory while still using some of the gwan functions. sadly, a tonne of errors follow -- WHEN I GCC from commandline not via G-WAN Startup.
In file included from /home/ec2-user/gwan/include/gwan.h:22,
from Xbufstream.h:10,
from Xbufstream.cpp:10:
/usr/include/time.h:199: error: ‘size_t’ does not name a type
.....
Anyone knows what the gwan g++ argument string looks like?
(odd the 1. and 1. its 1. and 2. in the editor)
First, this is not a linker issue: you have "undefined symbol" rather than "unresolved symbol" as an error.
This is simply an #include issue.
define the main() function in your script.cpp file.
there's a G-WAN folder dedicated to user-defined include files called /gwan/include but you can as well use /csp/my_include.hpp... if you are using the right syntax:
For example, having #include "toto.hpp" in /csp/hello.cpp lets me reach C++ functions defined and implemented in the gwan/include/toto.hpp file (or defined in toto.hpp and implemented in a pre-compiled library linked to your script with #pragma link).
If you rather use #include <toto.hpp> then the SYSTEM INCLUDE PATH will be searched instead (and this will work providing that your library was correctly installed).
If you want to use #include "toto.hpp" for a custom folder that was not setup in the system, you can use G-WAN's #pragma include "../my_folder" directive to specify its PATH or you can explicitely specify it in each include: #include "../my_folder/toto.hpp".
Nothing fancy there, only C/C++ dependancy rules apply (and G-WAN really helps by providing alternate ways that do not involve system settings).
For libraries (see the G-WAN examples for SQLite, Cairo, mySQL, cURL, etc.) you can either use pre-installed libraries that exported their location in SYSTEM variables... or put your library in the /gwan/libraries folder and their include file in the /gwan/include folder.
When writing your own libraries, remember that they need to be pre-compiled. This means that you obviously cannot use G-WAN symbols since your compiler may #include "gwan.h" (to have the definitions) but your linker will not know from where G-WAN symbols can be found. The way around is to always use the G-WAN API from the G-WAN scripts. Your custom libraries must either be general-purpose or buffer any payload intended to be used by G-WAN. No-double copy is needed since G-WAN provides the set_reply() call to let G-WAN use persistent replies built without the reply xbuffer provided by G-WAN servlets.
Now, a last word about linking (which was not the cause of your trouble but could participate to the confusion). If you mix C and C++, use extern C {} to wrap your C++ prototypes called from C (otherwise you will really have "unresolved symbols").
With all this information, you should be ready to face every possible situation.
the issue of referencing gwan.h symbols inside #include files can also be solved by moving all code into the header file, whether its .h or .hpp
its ungraceful but a fix nevertheless. and good enough for the simple extension i wanted.
looking into the /libraries/sqlite3/sqlite.h helped.
#gil, thanks for your time.
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'm working on a (rather horrible) project that involves importing a C++ class hierarchy through a dll interface. One of the more horrible details requires me know the 'decorated' names for the various class elements that are exposed - mostly member functions and static data.
There are many ways to achieve this - the assembly listing or map file, dumpbin, a dependency walker, the _FUNCDNAME_ macro, etc. Unfortunately, they all require me to actually compile the code or have the compiled dll - and all I have available is the header files. (That may leave you scratching your head for a minute - just take my word that it truly is a horrible project.)
Now, I can easily concoct something compilable from just the headers and use one of the above approaches. But if I can avoid it, that would be much better. So my question is: is there a way to browse decorated symbol names from within Visual Studio, a la Object Browser? I know that the decoration is technically done at compile time, but Intellisense does so many other things while you type that I'm hoping it might do this too.
If all else fail take that .h, rename it to .cpp, replace all semicolons (;) with
{
#pragma message(__FUNCDNAME__)
}
edit it a little, and compile it. You'll get your list.