I've got a program which shipped with a .tlb file to access some functions/objects (read variables etc.) with my own C++ program. I did a search and imported the .tlb file with:
#import "MyLib.tlb" named_guids no_namespace
I can also import it by using the libid from oleview.exe (ProgId does not work).
Even if I get some warnings (as follows), my program still runs:
C4278 ['TextOut', 'CreateEvent', 'DeleteFile'] is already a macro; use the 'rename' qualifier
But.. how can I gain access of the functions/objects now?
Sorry I'm a beginner so please be patient.
Does it work somehow with IDispatch? Do I need to import some more dll's or do I need more #include directives?
I'm using Visual C++ 2008 Express.
--
Edit: Ok sorry, I already have access to the header of the objects (I see "Application" in auto completion) but I have no idea how to get the objects.
Object Overview
And I think I found the related wikipedia article.
Importing type library gives you description of all the interfaces and identifiers of that library. Normally you should not include additionally any header files. You should just normally create these interfaces using COM smart pointer and call their methods:
CComPtr pInterface;
pInterface.CoCreateInstance(__uuidof("ClassNameFromTLB"));
pInterface->CallMethod();
Related
I've been trying to follow lazy foo's productions tutorial on sdl2 and I keep on running into the same issue. I made a template that links to the correct files and all and it worked for a while. But now when I create a project and include iostream for example, it tells me #using need c++/cli mode enabled.
So I then tried enabling it in the project settings but then it gave another error : "Cannot open metadata file iostream"
I tried :
Rebuilding the project and solution
Cleaning the project and solution
I read this question and its answers : Visual studio - getting error "Metadata file 'XYZ' could not be found" after edit continue
Tried this too : IntelliSense: "#using" requires C++/CLI to be enabled
All of the above did not work
Don't confuse #include, using and #using.
#using is used to import class libraries in C++/CLI, which is something you won't ever need unless you work with .NET libraries (but then usually you are better off just using C#, unless you are writing interop code).
#include is for including header files, which is what you normally do in "regular" C++. <iostream> is a regular standard library header, so you need #include (as in #include <iostream>).
using instead is used to bring names in the current scope (either the whole content of a namespace - as in the dreaded using namespace std;) or single names (as in using std::cout;). From C++11 it's also used to enable constructors inheritance and to create type aliases, but for the moment I don't think you need to worry about these uses.
But most importantly: please take the time to first learn the basics of the language from reputable sources before trying random stuff. All this #using mess wouldn't have arisen if you even just looked first at the classic hello would example you can find everywhere on the Internet.
I have some legacy C++ code.
I have DLL Bob.
I also have program Jane.
Program Jane imports Bob through his TLB file.
#import 'Bob.tlb'
Why does Jane use Bob like that?
Why doesn't Jane use Bob like this?
#import 'Bob.dll'
I have the source code for both sides.
Thanks for any help or pointers!
#importing a dll is equivalent to importing a tlb only when the dll contains the type library as the resource of ITypeLib type, as dictated by LoadTypeLib API call.
This is not always the case:
the dll doesn't have to contain the tlb as the resource
you might want to use a managed dll via COM interop: the dll doesn't contain the tlb and you have to generate it using tlbexp tool
there are probably other scenarios
TLB is type definition, which also can includes in DLL.
If you directly use #import *.tlb or #import *.dll, the MIDL Compiler would generate .tlh and .thi which used in following compiling steps.
It's not a good choice to directly #import.
If you #import the same .tlb in different cpp in same project, would introduce duplication .tlh & .tli files generated.
I need to import a type library (it's actually an .exe that gives access to a COM interface implementation).
The thing is that i want to do that but with the MinGW compiler and not VSC++.
There are many topics and threads on SO that explain the difference between the two #import directives, but the main idea is that we can't import type libraries with the MinGW import.
So why not try to load the type library programmatically at runtime using the
LoadTypeLibrary function and the ITypeLib interface.
Except that ITypeLib is rather used to describe the objects stored in the type library.
Now i have run on my .exe code similar to the one in this link here
to retrieve information about my .exe's methods and it shows what i expected (the same information i found in the generated .tlh with vc++)
Is there a way to call directly the library's functions ?? If yes :
Should I use the IDispatch::Invoke method ?
Is there a necessity for binding functions in the type library or mapping the class members (using ITypeComp::Bind) ?
Is there any way to convert the generated .tlh and .tli with vc++ into a normal .h & .cpp file and be able to use it with mingw compiler?
Thank you for your precisions !
I wish to use a COM dll in my C++ library.
The way I figured going about it, is to #import the dll's .tlb file, which I did :
#import "mycom.tlb" no_namespace
The problem is , I don't quite know where to place this declaration. should it be inside the H file or the CPP file? or maybe the stdafx.h file?
I tried placing it in the .cpp file , just for testing.
in the H file I have this member declared :
ILogicSecuredPtr m_pbLogic;
(where ILogicSecured is the interface I want to work with in my COM dll)
Then I added this in the constructor to instantiate the interface :
CoInitialize(NULL);
m_pbLogic(__uuidof(LogicSecured));
(where LogicSecured is the name of the object that implements the interface)
In the destructor I added :
CoUninitialize();
This won't compile however, no matter where I try to place the #import declaration.
it just doesn't recognize the ILogicSecured object.
I get this error in the H file :
Error 2 error C2146: syntax error : missing ';' before identifier 'm_pbLogic'
I should also mention that when I F12 (in Visual Studio) on the ILogicSecuredPtr declaration, it takes me to the tlh file just fine. So I know it recognizes it.
What am I doing wrong here?
Thanks alot.
Roey
The problem is that when the compiler parses the .h file it has not seen the #import yet. Since your project is small your best bet is to put #import into stdafx.h.
When you press F12 Visual Studio uses Intellisence database information that is formed parsing all the sources in order that might be different from the compilation order. So it's quite typical to have Intellisence know where something is declared and the compiler to not compile it at the same time.
What happens if you import a dll or tlb file is that the preprocessor generates a tlh and a tli file.
If the tlb is stable you could also generate the two files and include the tlh header as if its a normal header.
So the answer is put the #import where you would put the header because it is converted into an include of the tlh file.
I use it in the following way to make myself independent of the location of the MSADO15.dll and added the tlh file to my subversion.
#ifndef __ADO__H
#define __ADO__H
#ifdef REBUILD_ADO_HEADER
#import "C:\Programme\Gemeinsame Dateien\system\ado\MSADO15.DLL" rename_namespace("MyAdoNamespace") rename("EOF","EndOfFile")
#else // REBUILD_ADO_HEADER
#include "MSADO15.tlh"
#endif // REBUILD_ADO_HEADER
// Define ADO Namespace as global
using namespace MyAdoNamespace;
#endif // __ADO__H
In addition to the compile issues you are having, there are other problems with this design.
Generally, C++ libraries should not initialize COM on threads that it does not create. This can cause some nasty, hard to debug side effects. Consider updating the interface spec for your library to indicate that use of certain methods or objects require that COM be initialized. You should also specify the threading model required (STA, Free).
That said - the other thing you need to watch out for is calling CoUnitialize() before your smart pointer goes out of scope. This can also cause some hard to debug side-effects. If you're calling CoUnitialize() in the destructor of an object that contains a COM smart pointer, you'll need to explicitly release and detach the pointer prior to invoking CoUnitialize().
Have fun!
In all ADO C++ code I can find, there is a line
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" no_namespace rename("EOF", "EndOfFile")
I understand that this line "incorporate information from a type library", and that "The content of the type library is converted into C++ classes". What?
I'm also looking for the header file for ADO C++, but I can't seem to find it.
It's been a while since I played with that stuff, so what follows is a bit vague and may even be slightly inaccurate, but I hope it still helps:
The DLL implements COM interfaces, and contains a type library describing those interfaces. Among other things, a type library contains the IDL of those interfaces, which should be compiled to generate C++ header files that your program can use.
The #import directive automates the process of extracting the TLB from the DLL and compiling the interfaces it describes to generate the corresponding C++ headers, and #include-ing the generated headers.
#import will generate the header file for you. In this case have a look for msado15.tlh in the intermediate directory (ie, projectname/debug).