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.
Related
I've downloaded the latest copy from Latest Open EXR repo and compiled most everything without any problems. However, when I get to PyILMBase it fails.
There are two distinct issues with my attempts:
Error C2491 'PyImath::FixedArray::name': definition of dllimport function not allowed PyImath (...)\src\pyilmbase-2.2.1\PyImath\PyImath.cpp 41
and an import to unistd.h that kind of gets addressed Here
my question being, has anybody successfully compiled this for windows? It seems odd that I can't find any specific info about that compiling error. Am I missing something in the way that C++ works?
This project makes extensive use of whatever it is that causes the error C2491, so going in and changing it would be a little complicated
IlmBase is compiled as a shared library. A shared library must provide their function declarations in order your program can find them.
It's perform by declaring them as dllimport or dllexport depending on the situation.
__declspec(dllimport): imports the implementation from a DLL so your application can use it.
__declspec(dllexport): tells the linker that you want this object to be made available for other DLL's to import. It is used when creating a DLL that others can link to.
These keywords are generally handled by a single macro. In your case PYIMATH_EXPORT.
These lines are from PyImathTask.h
#if defined(PYIMATH_EXPORTS) // create library
#define PYIMATH_EXPORT __declspec(dllexport)
#else // use library
#define PYIMATH_EXPORT __declspec(dllimport)
#endif
So, because you want to make these functions available from your application, you must add PYIMATH_EXPORTS as a preprocessor definition.
Actually, PyIMath's properties mispells it - they've write it as PyImath_EXPORTS - ...
To fix that, in vs2015, go to the PyImath's properties > Configuration Properties > C/C++ > Preprocessor > Replace PyImath_EXPORTS by PYIMATH_EXPORTS.
It's probably the same thing for PyIex...
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.
In a *.cpp file, trying to use a third party lib:
#define DLL_IMPORT
#include <thirdParty.h>
// Third party header has code like:
// #ifdef DLL_IMPORT
// #define DLL_DECL __declspec(dllimport)
// fatal error C1001: An internal error has occurred in the compiler.
Alternative:
#define NO_DLL
#include <thirdParty.h>
// Third party header has code like:
// #elif defined(NO_DLL)
// #define DLL_DECL
// Compiles fine, but linker errors as can't find DLL functions
I can reproduce results by remove macros and #define all together and manually editing the third party files to have __declspec(dllimport) or not - so the preprocessor stuff above is just to show what's going on, it's not copy-paste.
Has anyone come across anything similar, or can hint at the cause? (which is created using CMake). Above is actual example of 2 line *.cpp that crashes so it's narrowed down to something in the #include.
The following also work fine:
Compile the examples provided by the third party (they provide a *.sln) that use dllimport/export so it doesn't appear to be the fault of the library
Compile the third party lib as part of the production project (so dllexport works fine)
I've trawled the project settings pages of the two projects to try and spot differences, but have come up blank. Of course, it's possible I'm missing something as those settings pages are not the easiest to navigate. I'll get access to VS2008 in a day or so, so can compare with that. The third party library is MySql++.
A compiler crash is definitely a bug in the compiler, so you're best off submitting an error report to the Microsoft Visual C++ team.
As for the error
#define DLL_DECL __declspec(dllimport)
is the wrong way to go about things. There should be some project setting you need to set, a pre-processing directive you can define instead if DLL_DECL, or simply including a different file.
Turns out it was because precompiled headers was turned on for the project trying to use the DLL.
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.
How can I remove this link warning? You can see code segment that causes this warning.
static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
//bla bla
// Exported DLL initialization is run in context of running application
extern "C" void WINAPI InitGuiCtrlsDLL()
{
// create a new CDynLinkLibrary for this app
new CDynLinkLibrary(GuiCtrlsDLL);
// nothing more to do
}
warning C4273: 'InitGuiCtrlsDLL' : inconsistent dll linkage
I have also export and import definitions, like:
#ifdef _GUICTRLS
#define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
#define GUI_CTRLS_EXPORT __declspec(dllimport)
#endif
The purpose of the preprocessor statements:
#ifdef _GUICTRLS
#define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
#define GUI_CTRLS_EXPORT __declspec(dllimport)
#endif
is to make sure that the header file declares the class or function as __declspec(dllexport) in the .dll where it is defined, and as __declspec(dllimport) for any other .dll that might want to use it.
For this to work, _GUICTRLS must be defined when compiling the exporting .dll, and not defined for any other .dll. Generally you would expect _GUICTRLS to be defined in the project properties, under C/C++ -> Preprocessor -> Preprocessor Definitions.
The compiler error you are seeing usually happens because either _GUICTRLS is not defined for the project that is doing the export, or it is defined for multiple projects, usually resulting from cutting an pasting from one project to another. You will also see this if _GUICTRLS is defined in a header file that is included in multiple projects.
There are multiple possibilities:
1) static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
You use AFX_EXTENSION_MODULE. This means that you are implementing an MFC extension DLL. For such extension dlls you have to define the preprocessor _AFXEXT. Set this in the C++ compiler settings of your Visual C++ project
see:
How To Use _declspec(dllexport) in an MFC Extension DLL: http://support.microsoft.com/kb/128199
AFX_EXTENSION_MODULE Structure: http://msdn.microsoft.com/en-us/library/sxfyk0zk.aspx
TN033: DLL Version of MFC: http://msdn.microsoft.com/en-us/library/hw85e4bb.aspx
2) It is likely that you have a duplicated definiton/declaration.
In addition to reading the warning message, pay attention to where it occurs if you have multiple projects as part of a workspace.
I wasted time looking for a problem in my DLL which was compiling and linking correctly. The workspace was also building the main application and my error was that I had inadvertently included a new (DLL) source file into the build file list of the application itself.
The main program requires the DLL header mynewdll.h to import things but does not require the source file mynewdll.cpp. (The code is brought in at run time with a DLL.) I have a habit of including header and code files into projects as a pair, and this is where I had gone wrong.
I would have detected the error much sooner if I had been alert and noticed that the DLL project linked with no errors and it was the main program that complained!
My DLL source code and project was error free and it was only the way I tried to build my executable that was faulty.
That warning is usually caused by a duplicate definition of a function with different use of dllimport. Are you sure you didn't do this?
[ CMake inconsistent dll linkage ]
I encountered the following issue + solution with the __declspec(dllexport) + __declspec(dllimport) :
# # #CMakeLists.txt
add_defintions(-DMYLIB=1)
# The above was the solution...
# (MYLIB is used in the standard ifdef + define MYLIB_EXPORT syntax)
# Below: seems to get overruled by other directory's headers:
set_source_files_properties( file1.h file2.h COMPILE_FLAGS "-DMYLIB=1")
This was annoying because a number of sources say to use the 'set source file properties' command to get better granularity but the doc is not clear on what happens to file1.h's declares when included from a different directory... better stick with add_definitions( -DMYLIB=1 ) for now!
To catch this problem: in your Foo.cpp file:
#include "export.h"
#if defined(MYLIB)
#if defined(OTHERLIB)
static_assert(0,"error, check your definitions!");
// OTHER depends on MY; can't have both of these flags being set!
#endif
#endif
struct OTHER_EXPORT foo
{
};
See that you are not defining the exported symbols in a different project. Also clean all the intermediate files by hand and recompile.
To elaborate the answer of damian with an example. I read it but didn't understand at first glance.
You have a shared library with a source file compiled in that contains the function. In a new project you use the library and in addition you compile also the source file to use the function (I forgot that it is already in the library). Within the library the functions label is exported, within the additional compiled source file the functions label is marked to be imported. That's the conflict.
In my case, error C4273 was caused by trying linking to .lib file from a DLL dynamic load tester app in Qt5 by msvc2017_64 toolchain. Removing the reference to .lib file by changing LIBS setting in .pro file have the problem solved.