I am experimenting with some Windows specific libraries in C++ (Using C libraries in my C++ code). I am trying to include objbase.h for CoCreateInstance() function:
#include <objbase.h>
// ...
HRESULT hr = CoCreateInstance(/* ... */);
My problem is with the VSCode C/C++ extension's intellisense. The code compiles ok, but the intellisense has some problems identifying this function. It has no problem with HRESULT, but for CoCreateInstance() it shows "identifier is undefined".
So I tried to look into the header file itself and figured out, the problem is, that the intellisense is recognizing some errors in the file and not letting me use the function, since it thinks it is not declared properly. It has no problem with the HRESULT, because it's just some simple typedef, that it understands. However the CoCreateInstance() is declared as:
WINOLEAPI CoCreateInstance( //...
where WINOLEAPI is a macro containing something like:
extern __declspec(dllimport) int __stdcall
I assume __declspec and __stdcall are some Windows specific keywords, and that the intellisense is simply not recognizing those, detecting an error, which makes the function undeclared, hence the "identifier is undefined" error.
Is this the cause of the problem? If so, is there any way to "teach" the intellisense something about those windows specific keywords? After all it is a Microsoft extension, I have no idea, why it wouldn't recognize Microsoft's C language extensions.
Update
I have found a temporary fix. See my answer below.
Update: Clarification
It seems that both combaseapi.h and objbase.h include all the dependencies they need, as even the intellisense is able to recognize __declspec (and __stdcall) as some "int __declspec" but it is unable to understand the syntax, where the type is surrounded by other keywords. It gives me an "explicit type is missing" error on the WINOLEAPI macro. When I replace the macro with its value explicitly as "extern __declspec(dllimport) int __stdcall", it gives me errors like "missing ;". So it seems, that it doesn't understand such syntax.
Add #include <windows.h> above objbaseapi.h
windows.h includes required definitions like for HRESULT ( Actually from winerror.h, but including windows.h should take care of it's dependents etc)
I found a temporary workaround. The WINOLEAPI macro is defined in the combaseapi.h file. I added these lines to the file after the WINOLEAPI definition:
// Original content of the file:
#ifdef _OLE32_
#define WINOLEAPI STDAPI
#define WINOLEAPI_(type) STDAPI_(type)
#else
#define WINOLEAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define WINOLEAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
#endif
// Added fix for VSCode intellisense:
#ifdef __INTELLISENSE__
#define WINOLEAPI EXTERN_C HRESULT
#define WINOLEAPI_(type) EXTERN_C type
#endif
Now when __INTELLISENSE__ is defined (It is not defined when compiling the code, but only when the intellisense examines the file.), it removes the unrecognized keywords from WINOLEAPI macro.
It would be nice though to apply some similar fix inside my code instead of modifying the included header. Also, this fixes only this particular situation, any of the other unsupported keywords must be treated separately. In my case, it fixes all problems in those two header files.
It works, but I would still appreciate if anyone provided some better solution.
Related
I was reading a header file and I noticed that the programmer has put a preprocessor identifier in front of the return values of functions in their declarations, as following.
#ifndef SAMPLE_API
#define SAMPLE_API
#endif
...
namespace SampleName
{
SAMPLE_API bool api_function();
...
}
What's the purpose of it and how does it work?
Edit: I am reading imgui.h from the IMGUI project.
By defining SAMPLE_API (on your compiler command line, in your Makefile / IDE environment etc.), you could add something to each function declaration in this header.
If you did not define SAMPLE_API, the first couple of lines...
#ifndef SAMPLE_API
#define SAMPLE_API
#endif
...make sure that SAMPLE_API is "defined away", i.e.
SAMPLE_API bool api_function();
...is preprocessed to...
bool api_function();
...so "nothing happens" (instead of "syntax error" when the compiler runs into SAMPLE_API and does not know what to do with it).
The usual reason for a construct like this SAMPLE_API symbol is to handle symbol export / import when building / using a library for Windows.
You would define SAMPLE_API to...
__declspec(dllexport) when building a library for Windows,
__declspec(dllimport) when using a library for Windows,
...so the symbols for the functions in question get exported / imported as necessary.
There are other things that could be done with such a preprocessor symbol (like deprecating functions, so that the linker will warn if they are being used), or other platform-specific stuff. But I would guess you're looking at dllexport / dllimport plumbing here.
In this particular case it does nothing. (Remember that the preprocessor does little more than trivial copying and pasting).
But, it might be useful in some instances to declare for example, a declspec for exporting a DLL function (in which case it would be #DEFINEd to something less trivial. Needless to say, that kind of thing is not formally part of the C++ standard, but rather is likely exploiting compiler extensions.
I've got a dll from a vendor I want to use in a C++ Visual Studio 2012 project. It comes with a .lib file.
When linking I get:
Error 1 error LNK2019: unresolved external symbol __imp__FT_CreateDeviceInfoList referenced in function "int __cdecl Ftexam(void)" (?Ftexam##YAHXZ) C:\Users\Terry\Documents\Visual Studio 2012\Projects\Win32Project1\Win32Project1\ftexam.obj ftexample
I've read similar posts but I'm not getting anywhere. I think I'm doing everything according to those answers, but I still get a undefined reference error when linking.
I've added the dll.lib file to the /Linker/Addional Dependencies list.
I've made sure the dll.h file is included in my source
I've put the dll.lib file with in my project directory and made sure that if I remove it from there,I get cannot find dll.lib when linking (i.e., it is "in the build")
In my supplied dll.h header file I have this:
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
.
.
#ifdef __cplusplus
extern "C" {
#endif
typedef ULONG FT_STATUS;
.
.
DLL_API FT_STATUS FT_CreateDeviceInfoList(
LPDWORD lpdwNumDevs
);
and my calling code is:
#include dll.h
int Ftexam(){
FT_STATUS ftStatus=0;
DWORD numDevs = 0;
// create the device information list
ftStatus = FT_CreateDeviceInfoList(&numDevs);
}
I realize there is probably some name mangling going on so I looked at the DLL symbols using depends. It lists these exports with the "Undecorate C++ functions" option disabled, (so, these are the unmangled exports):
FT_Open
FT_Close
FT_Read
....
FT_CyclePort
FT_CreateDeviceInfoList< <<<<<this reference!!!!
FT_GetDeviceInfoList
The identified export above obviously does not match __imp__FT_CreateDeviceInfoList
Is there a tool around that can look at the definitions in a .lib file, or some way for visual studio to display that?
UPDATE:
With the use of dumpbin I was able to see the symbol in the .lib was
__imp_FT_CreateDeviceInfoList
instead of
__imp__FT_CreateDeviceInfoList
this I tracked to the .lib for the 64 bit version of the DLL instead of the 32 bit version. (One of the combinations I tried to solve this in the first place).
To simplify the post, I had indicated that the header contained:
DLL_API FT_STATUS FT_CreateDeviceInfoList(LPDWORD lpdwNumDevs);
When in fact, it actually contains:
DLL_API FT_STATUS WINAPI FT_CreateDeviceInfoList(LPDWORD lpdwNumDevs);
because WINAPI was #defined
so changing
#define WINAPI
to
#define WINAPI __stdcall
along with having the correct .lib fixed the issue.
FT_CreateDeviceInfoList() is not declaring any calling convention in the .h file, so it uses whatever the compiler's default calling convention is. Your compiler is defaulting to __cdecl, which is normal behavior for most C++ compilers. Chances are that the compiler that created the DLL is actually using a different default calling convention instead. Try editing the .h file to specify __stdcall, for example, and see if it makes any difference, eg:
DLL_API FT_STATUS __stdcall FT_CreateDeviceInfoList(LPDWORD lpdwNumDevs);
Most DLL vendors use __stdcall for compatibility with the widest selection of compilers, not just C/C++ compilers, though some vendors do use __cdecl or even __fastcall (which is implemented differently by different compiler vendors, so watch out with that one).
Worse case scenario, you can use a disassembler, like IDA or WinDASM, or just use your IDE's own debugger, to look at the actual assembly code for FT_CreateDeviceInfoList() inside the DLL and see how it is managing the call stack when accessing the lpdwNumDevs parameter and returning the FT_STATUS value. That will tell you exactly which calling convention it is actually using.
UPDATE: doing some online searches, I see many examples of .NET code that call FT_CreateDeviceInfoList() with the __stdcall calling convention applied to its declaration, so that is a good place to start. If that works, then you should contact the DLL vendor and ask them to fix their .h file accordingly.
Open a Visual Studio command prompt. Fire the following command to list the symbols in the lib file:
dumpbin /all dll.lib
Redirect the above to a text file, as the output scrolls off quickly
What you're doing should work as far as I can see. But you can always just forget about the .lib file and use the DLL directly, loading it with LoadLibrary and getting the addresses of the functions you want to use with GetProcAddress.
I have a bunch of Dll's in my project, using VStudio 9.0 compiler, pre-compiled headers are used for all my Dll's. The dll's loading process is done by implicit caller (.dll, .lib and header must be supplied).
I typically create a different macro definition file per dll, for instance if my current Dll is called MYMacroDll I add a file _MyMacroDll.h which contains:
#ifndef _MYMACRODLL_H_
#define _MYMACRODLL_H_
#ifdef _WIN32
#ifdef MYMACRODLL_EXPORTS
#define MYMACRODLL_API __declspec(dllexport)
#else
#define MYMACRODLL_API __declspec(dllimport)
#endif
#define MYMACRODLL_CALL __cdecl
#else
#define MYMACRODLL_API
#define MYMACRODLL_CALL
#endif
#endif
I know the code can be simplified but I keep the last defines for portability, at least, that's what I understood...
The pre-compiled header file pch.h, will always include the macro definition file _MyMacroDll.h, this makes things easier to me, 'cause later I can decide whether a new class or function will be interfaced or not. This so far works correct.
The confusion comes from using the dll interfaces in another dll; let's suppose a second dll ImageLoaderDll. This one uses instances or references of one (or several) of the interfaced classes/functions in _MyMacroDll. At first glance I guessed there was no need of including the _MyMacroDll.h, but when compiling the ImageLoaderDll it complains with
error C2470: '_AnInterfaceClassFromMyMacro' : looks like a function definition, but there is no parameter list; skipping apparent body
Then I have to include the _MyMacroDll.h in the pre-compiler header file of the other Dll, my project is becoming really messy and I find more and more useless dependencies.
What am doing wrong? Is there another way of setting up the macro definitions so I can avoid adding it to the client Dll's? Am not an expert regarding software design, but in this situation the more decoupled the better.
Hope my explanation was good enough.
If you are using the DLL interface from MyMacroDll in ImageLoaderDll, then you do have a dependency. ImageLoaderDll should include _MyMacroDll.h, otherwise you can't call its functions correctly. It's exactly the same as including <string.h> when you want to call strlen.
I've managed to get input hooks working, but now I'm kinda lost with putting them into a library.
I have a simple header with INPUTHOOK_EXPORTS defined in the IDE, so the dll exports (Visual Studio).
#pragma once
#ifdef INPUTHOOK_EXPORTS
#define INPUTHOOK_API __declspec(dllexport)
#else
#define INPUTHOOK_API __declspec(dllimport)
#endif
INPUTHOOK_API void InstallInputHook();
INPUTHOOK_API void RemoveInputHook();
and of course:
The cpp file
The thing is, when I try to compile this library, I get two unresolved externals, one for SetWindowsHookEx and for UnhookWindowsHookEx respectively. Why these two functions are not available, while others are and without any problem? As far as I see, I do have the includes right.
Thank you
SetWindowsHookEx is a macro that should turn into SetWindowsHookExA' for ascii orSetWindowsHookExWfor wchar. Similary forUnhookWindowsHookEx` .
The error reported should be specific to which function is missing - A or W - which seems to indicate for some reason the macro is not in place.
You seem to be missing winuser.h in the cpp, however this or an equivalent may be in the pre-compiled stdafx.h header.
You need to include user32.lib while building (linking) your library (normally in the default included libs).
From MSDN topic LowLevelKeyboardProc:
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
I generated a DLL in Visual from a C++ code. Dependency Walker sees 3 functions exported as C functions.
I made an SCons project to do the generate the DLL, and 2 of the 3 functions are not seen as C functions.
What makes a function seen as a or C++ function, without modifying the code ? It must be in the compilation/linking options, but I didn't find any relevant thing.
The function are prefixed by a macro : AM_LIB_EXPORT
In the .h, I have :
#ifdef _WIN32
#define AM_LIB_EXPORT __declspec(dllexport)
#else
#define AM_LIB_EXPORT
#endif // _WIN32
Thanks.
What makes a function seen as a or C++ function, without modifying the code ?
A function compiled by a C++ compiler is automatically a 'C++-function' and name-mangling occurs to resolve C++ features such as namespaces and overloading.
In order to get 'C' export names, one must use the aforementioned extern "C" qualifier in the function declaration. Alternatively a huge extern "C" { .. } block around the header containing the prototypes.
If this does not solve your issue, its maybe related to dllimport/dllexport. If you #define AM_LIB_EXPORT __declspec(dllexport) in your DLL build, you'll typically also need to make it dllimport for apps linking against your DLL in order for the linker to know where to fetch the symbols from.
Is this a name mangling issue? If you don't use extern "C" around your function declarations, they will get name-mangled.
I found the reason :
The export was also added as additionnal command line option (/EXPORT). In this case, it is exported as a C function. I don't understand why...
I removed this additionnal command line switch.
Thank you all.
I still don't know how to mark a thread as "resolved" ?