I am exporting a global variable from a dll using __declspec(dllexport) and importing the same in the client exe using __declspec(dllimport).
The global variable in the dll is being updated with time in a separate thread. I want to receive this updated data in my client .exe, but I am not getting it. What I get is the only initial value of the global variable every time I read the data using a timer in the client exe.
What is the explanation of such a behavior? and what can I do to achieve what I want to achieve? Is there an option without including get() and set() exported functions from the dll?
Here is the code that is exported from dll:
typedef struct{
int iTotalQueues;
int iCurrentQueue;
wchar_t szQueueName[100];
}UPDATE_STATUS_DATA;
__declspec(dllexport) UPDATE_STATUS_DATA UpdateStatusData;
This structure members are updated in a loop for a long time. The updating code is in the dll itself.
Here is the code that is imported in the exe:
typedef struct{
int iTotalQueues;
int iCurrentQueue;
wchar_t szQueueName[100];
}UPDATE_STATUS_DATA;
__declspec(dllimport) UPDATE_STATUS_DATA UpdateStatusData;
I am reading this data inside a timer response and not getting the updated values.
The code in your question as you would expect when built into a simple test project. So, here are the two explanations that I can concoct:
You are taking a copy of UpdateStatusData in your executable. And so the changes to the value of UpdateStatusData made in the DLL do not get reflected in the copy.
Your DLL is, for some reason, not modifying the struct.
Related
I have been having issues using an anonymous mutex (boost::interprocess::interprocess_mutex) in a boost::interprocess::managed_shared_memory instance. Namely, issues arise if the software crashes; the mutex may remain locked (depending on its state at time of crash). It can make debugging interesting too :).
My understanding is that I can substitute the interprocess_mutex with boost::interprocess::file_lock (FL). #DaveF posted some questions that I would like to build upon. I'd like to have a good understanding what I'm getting myself into before I put FL into use.
Can I use an anonymous boost::interprocess::condition_variable (CV) with FL? Having looked through the code, it appears that it will work.
In using a CV, am I opening myself up to the same problems I have experienced when using mutex (ie. if the application unexpectedly ends without proper cleanup/finalisation)?
What is the best way to create a FL. I've thought about something similar to the following...
Note code may not compile:
namespace bi = boost::interprocess;
namespace bf = boost::filesystem;
const std::string strSharedMemName = std::string("cp_shdmem_") + std::to_string(nIdx);
const std::string strNamedMutexName = strSharedMemName + "_mtx";
// I'm working on Linux, but would like to Boost to create a temporary file path.
const bf::path pathTmpFile =
bf::temp_directory_path() / (strNamedMutexName + ".txt");
{
// 1. So can I just create the file? What happens if it exists? Boost docs say this
// about the file_lock constructor:
// "Throws interprocess_exception if the file does not exist
// or there are no operating system resources."
// 2. What happens if file already exists?
bf::ofstream f(pathTmpFile);
}
// Create.
bi::file_lock lockFile(pathTmpFile.string().c_str());
// Lock.
bi::scoped_lock<bi::file_lock> lockNamed(lockFile);
Platform specifics:
Ubuntu 17.10
Boost 1.63
GCC 7.2
When using 'Load-Time Dynamic Linking'(using an import library .lib in compilation that loads a dll when the module is loaded) in a Win32 application, is it possible to affect the search order?
The goal is to have a library loaded using the normal search order, with a back-up path if one is not found on the normal path.
Example: foo.lib is linked in the project. At load time:
If foo.dll is present in the System path or any of the other paths mentioned in Dynamic-Link Library Search Order then it will be loaded.
Else mySpecifiedPath/foo.dll will be loaded.
Clarification: The back-up dll should only be loaded if no version of the dll is found in the standard LoadLibrary search paths.
Leaving the old answer at the bottom and adding a new one at the top:
The combination of delay-loading and the delay-load Failure Hook as described at provides a nice way to handle this.
Register the failure hook that loads the back-up dll before using any symbol from the library.
#include <Windows.h>
#include "foo.h"
#include <delayimp.h>
//access to set the failure hook
ExternC PfnDliHook __pfnDliFailureHook2;
const char* dllName = "foo.dll";
const char* dllBackupPath = "pathToBackup\\foo.dll";
FARPROC WINAPI DelayLoadHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
//if the failure was failure to load the designated dll
if (dliNotify == dliFailLoadLib &&
strcmp(dllName, pdli->szDll) == 0 &&
pdli->dwLastError == ERROR_MOD_NOT_FOUND)
{
printf("loading back-up dll\n");
//return the successfully loaded back-up lib,
//or 0, the LoadLibrary fails here
HMODULE lib = LoadLibraryA(dllBackupPath);
return (FARPROC)lib;
}
return 0;
}
int main()
{
//set the Failure Hook
__pfnDliFailureHook2 = &DelayLoadHook;
//when this function is called the library will be loaded
//from standard paths. If it is not found the Failure Hook
//set above will be called.
int test = ::intReturningFuncFromFooDll();
printf("%d", test);
getchar();
return 0;
}
===========old answer below==============
Looks like what I was looking for is delay-loading, as mentioned in the comment by IInspectable. I found information regarding this:
Linker Support for Delay-Loaded DLLs
Here is some code demonstrating the usage I mentioned in the original post:
//load the dll using the normal search
HMODULE lib = LoadLibrary( L"foo.dll" );
//if unsuccessful, try a specified path
if (lib == NULL)
{
LoadLibrary( L"mySpecifiedPath/foo.dll" );
}
if (lib == NULL)
{
//make sure that the library is not used,
//or exit the application, as it was not found
}
Thanks for the help!
edit to old answer: This dynamic loading would be used before any symbol from the library is used. The delay loaded fills out the symbol addresses using the module loaded here the first time a symbol from the library is accessed.
Looking at the Dynamic-Link Library Search Order documentation, it should be obvious, that the final location searched is the PATH environment variable. Applying that knowledge, the easiest solution that meets all your requirements is to append the backup location to the PATH variable.
This could be done in two ways:
An external launcher: The CreateProcess API call allows an application, to pass a custom environment to the new process through the lpEnvironment argument. The current process' environment block can be queried by calling GetEnvironmentStrings.
Enable delay-loading of the desired DLL(s) using the /DELAYLOAD linker option, and modify the process' environment at application startup. After retrieving the PATH environment variable (using GetEnvironmentVariable), it can be modified and updated in the environment block by calling SetEnvironmentVariable.
I want to use time related method and function in Win32 VC++ application. VC++ provides CTime class. I want to know that using CTime class in non mfc project is safe. Is there any alternatives for CTime class for using in non mfc win32 application.
Thank you.
You can try using GetSystemTime;
Retrieves the current system date and time. The system time is
expressed in Coordinated Universal Time (UTC).
To retrieve the current system date and time in local time, use the
GetLocalTime function.
A sample code piece.
#include <windows.h>
#include <iostream>
void main(){
SYSTEMTIME st;
GetSystemTime(&st);
char currentTime[84] = "";
sprintf_s(currentTime,"%d/%d/%d %d:%d:%d %d",
st.wDay,st.wMonth,st.wYear, st.wHour,
st.wMinute, st.wSecond , st.wMilliseconds);
std::cout<<"time: "<<currentTime;
getchar();
}
Using MFC in a console (non GUI) application is safe. Even the Project Wizard to generate a Win32 Console Application has a checkbox to specify whether to include the MFC libraries or not.
I have slight problem or misunderstanding with hiding symbols in xcode 4.6. I have searched everywhere in the web and cant find any posts having the same issue.
Currently I have created a framework project with a simple header file containing so:
class Test
{
public:
Test(){}
Test(){}
};
int a(int n) {return n;}
__attribute__((visibility("hidden"))) int b(int n) {return n;}
__attribute__((visibility("default"))) int c(int n) {return n;}
class X
{
public:
virtual ~X();
};
class __attribute__((visibility("hidden"))) Y
{
public:
virtual ~Y();
};
class __attribute__((visibility("default"))) Z
{
public:
virtual ~Z();
};
X::~X() { }
Y::~Y() { }
Z::~Z() { }
In the project settings i have made sure that "Symbols hidden by default" is switched to YES and therefore only the functions int c and the class z will be exported or visible to other projects.
I build the framework with no errors or warnings and then copy/add it to a cocoa application for testing.
I am able to include the header file but I am still able to access all classes and functions.
I hope someone can explain why or where i am going wrong or have encountered this problem before?
regards
Your problem is, you are declaring everything in the header file. That means even if the symbols are not exported, when you import the header file into another file, these symbols are re-created in the project where you imported the header and thus they are of course available within this project.
I'm trying to explain this to you by a simpler sample. Assume you have two files, MyLib.h and MyLib.c.
MyLib.h:
int add(int a, int b);
MyLib.c:
int add(int a, int b) { return a + b };
If you now give add a hidden visibility and compile everything to a library (MyLib), the library will have no symbol for add (as it is hidden). As a result, if you include MyLib.h into another file, make a call to the add function there and finally link this file against MyLib, you will get a linker error, since the linker will complain that it cannot find an implementation for add (it only has a declaration from the H file).
However, if you pack the function into the header itself, so MyLib.h is:
int add(int a, int b) { return a + b };
and you give add a hidden visibility, the library will also have no symbol for add, but when you include the header into another file, this header will create a symbol for add in exactly the file that imported it and thus of course you will not get a linker error and be able to call add.
Importing a H file just means copying the whole content of the H file to the location where the import instruction has been found. Now think about it: If you copy the whole content of the H file in your question to the top of the file where you are including it, of course all symbols declared there are visible and usable in the current project. Why wouldn't they be visible or useable? They are not in the library, yes, but they are in the header and thus do get compiled when your other project is compiled.
Symbols that are supposed to not be visible outside your current project ("hidden" symbols) should never appear in any public header file of your framework. Why would you announce the existence of symbols in a header files that cannot be used anyway? Actually, in most cases not exposing the symbols in the header file is already enough to prevent people from using them. The reason for not exporting them either is only that if a symbol exists, it can be used, even if it is not exposed by any header file (therefor you just need to write your own header file or declaring it as external symbol directly in your code). So making symbols hidden is just a safeguard to make sure that it cannot be used under any circumstances.
I'm trying to implement http://msdn.microsoft.com/en-us/library/dd377634%28v=VS.85%29.aspx on Qt, to generate a poster frame/thumbnail for video files.
I have installed both Windows Vista and Windows 7 SDK. I put:
#include "qedit.h"
in my code (noting there is also one in C:\Qt\2010.04\mingw\include), I add:
win32:INCLUDEPATH += $$quote(C:/WindowsSDK/v6.0/Include)
to my *.pro file. I compile and get " error: sal.h: No such file or directory". Finding this in VC++ I add
win32:INCLUDEPATH += $$quote(C:/Program Files/Microsoft Visual Studio 10.0/VC/include)
And now have 1400 compile errors. So, I abandon that and just add:
win32:LIBS += C:/WindowsSDK/v7.1/Lib/strmiids.lib
to my *.pro file and try to run (without including any headers):
IMediaDet mediadet;
But then I get "error: IMediaDet: No such file or directory".
#include "qedit.h"
gives me the same error (it looks like it's pointing to the Qt version) and
#include "C:/WindowsSDK/v6.0/Include/qedit.h"
goes back to generating 1000's of compile errors.
Sigh, so much trouble for what should be 10 lines of code...
Thanks for your comments and help
Since you say you are "a C++/Qt newbie" then I suspect that the real issue may be that you are attempting to load the library yourself rather than simply linking your application to it?
To link an external library into your application with Qt all you need to do is modify the appropriate .pro file. For example if the library is called libfoo.dll you just add
LIBS += -L/path/to/lib -lfoo
You can find more information about this in the relevant section of the qmake manual. Note that qmake commonly employs Unix-like notation and transparently does the right thing on Windows.
Having done this you can include the library's headers and use whatever classes and functions it provides. Note that you can also modify the project file to append an include path to help pick up the headers eg.
INCLUDEPATH += /path/to/headers
Again, more information in the relevant section of the qmake manual.
Note that both these project variables work with relative paths and will happily work with .. to mean "go up a directory" on all platforms.
Note that qedit.h requires dxtrans.h, which is part of DirectX9 SDK.
You can find dxtrans.h in DirectX SDK from August 2006. Note that dxtrans.h is removed from newer DirectX SDKs.
Do you have access to the source of the external library? The following assumes that you do.
What I do when I need to extract a class from a library with only functions resolved, is to use a factory function in the library.
// Library.h
class SomeClass {
public:
SomeClass(std::string name);
// ... class declaration goes here
};
In the cpp file, I use a proxy function outside the extern "C" when my constructor requires C++ parameters (e.g. types such as std::string), which I pass as a pointer to prevent the compiler from messing up the signature between C and C++. You can avoid the extra step if your constructor doesn't require parameters, and call new SomeClass() directly from the exported function.
// Library.cpp
#include "Library.h"
SomeClass::SomeClass(std::string name)
{
// implementation details
}
// Proxy function to handle C++ types
SomeClass *ImplCreateClass(std::string* name) { return new SomeClass(*name); }
extern "C"
{
// Notice the pass-by-pointer for C++ types
SomeClass *CreateClass(std::string* name) { return ImplCreateClass(name); }
}
Then, in the application that uses the library :
// Application.cpp
#include "Library.h"
typedef SomeClass* (*FactoryFunction)(std::string*);
// ...
QLibrary library(QString("MyLibrary"));
FactoryFunction factory = reinterpret_cast(library.resolve("CreateClass"));
std::string name("foobar");
SomeClass *myInstance = factory(&name);
You now hold an instance of the class declared in the library.