Including DirectShow library into Qt for video thumbnail - windows

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.

Related

using qt with adtf. Generation of moc file during build time?

I am trying to use qt with adtf 3.3 .
From the documentation of adtf (https://support.digitalwerk.net/adtf/v3/adtf_html/page_external_dependencies.html) and example from adtf using qt(https://support.digitalwerk.net/adtf/v3/adtf_html/page_demo_qt_video_display_code.html).
Brief intro about what i am trying to do.
I have created one ui file using QtDesigner and then i generated manually header file using uic compiler then also generated moc file since i have signal and slots functionality i also need moc file to call metaobjects.
So Now i would like to do is instead of generating manually header file using uic and moc file i wanted to generate moc file during build time using
set(CMAKE_AUTOMOC_ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
the reason why i am doing like this if i change some functionality or added some signal and slots then i need to generate separatley and add in the sources file.
So basically my header file generated by uic contains info about objects used in qt form. Basically it translates xml file type which contains information about ui to header file using uic compiler.
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QTableWidget>
#include <QtWidgets/QWidget>
#include <QLineEdit>
QT_BEGIN_NAMESPACE
class Ui_Form
{
public:
QGroupBox *groupBox_dummy;
void setupUi(QWidget *Form)
{
if (Form->objectName().isEmpty())
Form->setObjectName(QStringLiteral("Form"));
//Form->resize(960, 480);
Form->setFixedSize(960, 480);
/*Contains several qobjects removed intentionally as it makes post so long*/
retranslateUi(Form);
QMetaObject::connectSlotsByName(Form);
} // setupUi
void retranslateUi(QWidget *Form)
{
} // retranslateUi
};
namespace Ui {
class Form: public Ui_Form {};
} // namespace Ui
QT_END_NAMESPACE
and then i have a moc file generated my moc compiler they are always generated for all QObject classes. They are absolutely required for meta stuff to work, so things like: signals for example.
My CMAKELists look like
set (CMAKE_CXX_STANDARD 11)
include(FetchContent)
find_package(ADTF REQUIRED HINTS ${ADTF_DIR} COMPONENTS filtersdk ui)
adtf_use_qt(Widgets)
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
find_package(Eigen3 CONFIG REQUIRED HINTS ${CMAKE_SOURCE_DIR}/libs/eigen/share/eigen3/cmake)
set(OpenCV_STATIC ON)
find_package(OpenCV CONFIG REQUIRED HINTS ${CMAKE_SOURCE_DIR}/libs/opencv)
# include directories
include_directories(inc)
include_directories(${CMAKE_BINARY_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${EIGEN3_INCLUDE_DIR})
# specify target
set(TARGET_NAME dummy)
set (TARGET_SOURCES
inc/uic_dummy.h->file generated by uic compiler. this code snipper is shown above
inc/dummy.h -> this basically contains several methods like createview and severalt hings and also slots (for qt functionality)
inc/stdafx.h -> contains all includes in this file
src/dummy.cpp->definitions of all the functions mentioned in dummy.h
src/moc_dummy.cpp-> moc file everytime i need to keep in the sources list. However i want to generate it in build time instead of saying like this uisng CMAKE_AUTOMOC ON
)
adtf_add_filter(${TARGET_NAME} ${TARGET_SOURCES})
target_link_libraries(${TARGET_NAME} PRIVATE Qt5::Widgets ${OpenCV_LIBS} adtf::ui)
adtf_disable_qt_warnings(${TARGET_NAME})
adtf_install_target(${TARGET_NAME} ${CMAKE_INSTALL_PREFIX}/dummy/dummy)
adtf_create_plugindescription(
/*removed intentionall as it is not the area of the concern in this scenario*/
)
So my question is can i generate moc file in build time?
Since I am using adtf_use_qt(widgets) and in cmake gui i point out qt_dir then everything works fine. However i need to keep moc file in the sources.
Normally when i use qt withouf adtf i basicall use find_package(qt) and also use
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE AUTORCC ON)
Then i will only keep my ui file in the sources and then it generates
everyhting forme. Ideally i would like to know if i can do the same for adtf.
Please excuse me if my question is not clear.If you need any more info please ask i will try to elaborate in a much better way than this. Thanks
are you still having trouble creating your moc files?
Maybe you only have to add your xxx.ui file to the filter sources.
The ui_xxx.h could be included within your source files.
For example:
set(PLUGIN_TARGETNAME your_filter)
adtf_add_filter(${PLUGIN_TARGETNAME}
${PLUGIN_TARGETNAME}.h
${PLUGIN_TARGETNAME}.cpp
${PLUGIN_TARGETNAME}.ui
)
target_link_libraries(${PLUGIN_TARGETNAME} PRIVATE
adtf::systemsdk
adtf::filtersdk
adtf::ui)
set_target_properties(${PLUGIN_TARGETNAME} PROPERTIES FOLDER src)
adtf_create_plugindescription(
TARGET ${PLUGIN_TARGETNAME}
PLUGIN_SUBDIR "bin")
set_target_properties(${PLUGIN_TARGETNAME}
PROPERTIES AUTOMOC ON AUTOUIC ON AUTOGEN_TARGET_DEPENDS ${PLUGIN_TARGETNAME}.ui)

Specify a "back-up" load path with Load-Time Dynamic Linking?

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.

How do you Initialize a Nonregistered COM DLL?

Recently, some of our clients lost their XAudio2_7.dll from their C:/Windows/System32 directory, and now they can't hear any audio. Reinstalling DirectX or registering the dll normally would be sufficient enough to fix this problem, but we're looking for a solution that does not require admin rights. This is for Windows 7. Applications are written in CPP, and some of them are 32 bit and the rest are 64 bit.
There is a local copy of XAudio2_7.dll within the same directory of the exe, but that is not loaded unless that dll is registered since it's a COM dll. Registering for the current user (using "Regsvr32.exe /n /i:user XAudio2_7.dll") does not work since the dll does not implement a required interface "DllInstall".
One approach I've tried is to statically link a .lib of XAudio instead of using a dynamic link. Microsoft does not distribute XAudio2_7.lib with DirectX SDK. "No versions of the DirectX SDK contain the xaudio2.lib import library. DirectX SDK versions use COM to create a new XAudio2 object." msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2create%28v=vs.85%29.aspx
Granted, this suggests that it may not be possible to use a static XAudio library even if I created one since it sounds like it depends on external objects defined in other libraries. It was still worth testing in case my hypothesis is incorrect.
Following the steps mentioned in this link: adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/
I didn't get very far with this method. Outside of the articles being dated, there were a couple problems with this. The MS link within the blog mentions this is for 32-bit dlls. Even for 32-bit dlls, dumpbin didn't work since it only exported the interface functions.
Dump of file C:\XAudioTest\32Bit\XAudio2_7.dll
File Type: DLL
Section contains the following exports for xaudio2.dll
00000000 characteristics
4C064181 time date stamp Wed Jun 02 07:33:21 2010
0.00 version
1 ordinal base
4 number of functions
4 number of names
ordinal hint RVA name
1 0 00030AA0 DllCanUnloadNow
2 1 00031150 DllGetClassObject
3 2 00031470 DllRegisterServer
4 3 000314D0 DllUnregisterServer
Summary
C000 .data
1000 .no_bbt
4000 .reloc
1000 .rsrc
7B000 .text
Later, I found this quote from another MSDN article. "The COM standard requires that COM DLLs export DllCanUnloadNow, DllGetClassObject, DllRegisterServer and DllUnregisterServer. Typically they will export nothing else. This means that you cannot get COM object or method information using dumpbin.exe." msdn.microsoft.com/en-us/library/aa446532.aspx
I've also tried using a third party program that claims it's able to create a .lib from a COM dll. www.binary-soft.com/dll2lib/dll2lib.htm
Although this did generate a 32-bit .lib file, compiling with the lib file generated unresolved external symbols. This utility does come with methods to handle unresolved symbols, but entering anything within Symbol Finder or Advanced Conversion Options would crash. Looking in the latest release notes (3.00), I found that they added support for Vista and no mentions for Windows 7. Also this doesn't work for 64-bit dlls.
I've tried another approach is to change the initialization sequence to use a nonregistered COM DLL described in this link: Use COM Object from DLL without register
The initialization code looks similar to this:
HMODULE audioLib = LoadLibrary(TEXT("XAudio2_7.dll"));
if (audioLib == NULL)
{
debugf(TEXT("Failed to create COM object. Unable to load XAudio2_7.dll library. GetLastError: %d"), GetLastError());
return;
}
typedef HRESULT (WINAPI* Function_DllGCO) (REFCLSID, REFIID, LPVOID*);
Function_DllGCO processAddress = (Function_DllGCO)GetProcAddress(audioLib, "DllGetClassObject");
if (processAddress == NULL)
{
debugf(TEXT("COM DLL failed to find the process address to interface function 'DllgetClassObject' within the XAudio2_7.dll. GetLastError: %d"), GetLastError());
return;
}
class __declspec(uuid("{5a508685-a254-4fba-9b82-9a24b00306af}")) xAudioGUID;
REFCLSID classID = __uuidof(xAudioGUID);
class __declspec(uuid("{00000001-0000-0000-c000-000000000046}")) classFactoryGUID;
REFIID classFactoryID = __uuidof(classFactoryGUID);
IClassFactory* ClassFactory = NULL;
if (processAddress(classID, classFactoryID, reinterpret_cast<LPVOID*>(&ClassFactory)) != S_OK)
{
debugf(TEXT("Failed to execute function pointer to DLLGetClassObject. GetLastError: %d"), GetLastError());
return;
}
class __declspec(uuid("{00000000-0000-0000-C000-000000000046}")) unknownGUID;
REFIID unknownID = __uuidof(unknownGUID);
if (ClassFactory->CreateInstance(NULL, unknownID, reinterpret_cast<void**>(&ClassFactory)) != S_OK)
{
debugf(TEXT("Class factory for XAudio2_7 failed to create an object instance. GetLastError: %d"), GetLastError());
ClassFactory->Release();
return;
}
if( XAudio2Create( &XAudio2, 0, AUDIO_THREAD) != S_OK ) //Fails here with error number: 1008 (An attempt was made to reference a token that does not exist.)
{
debugf( NAME_Init, TEXT( "Failed to create XAudio2 interface: GetLastError: %d" ), GetLastError());
return;
}
//Do other things
All WinAPI function calls passed excluding the XAudio2Create function. I'm uncertain why XAudio2Create is not using the object created from the factory, and I don't know what I need to do to get it to use that object. I'm still investigating what I can do here, but it's difficult to debug closed source libraries.
Before I knew about COM DLLs, a method I've tried is to use DLL-Redirection to force an application to use a particular DLL. Using the process described here: DLL redirection using manifests
XAudio2Create still failed. I don't have a strong strategy in identifying what's wrong with the manifest. I also haven't found much up to date documentation regarding manifests for dll redirection. From the sounds of this is this mostly used to load a particular DLL version. I don't think DLL redirection is the method I need since there is already a local copy of XAudio2_7 within the same directory of the exe, which means it should take precedence over the XAudio2_7 within the system directory according to: msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
Note: I removed the hyper links for some addresses since I don't have enough reputation points to post more than 2 links.
Have you tried registration-free activation?

How to get the object file in a static library with scons

I am using scons to build my project. Now I got a problem.
I use
env.StaticLibrary('a', [a1.o, a2.o])
to get a static library "liba.a".
Now I pass "liba.a" to another part of my project, in the part, I will generate another static library named "libb.a", and this will merge "liba.a" with some other object files.
The code like this:
env.StaticLibrary('b', ['liba.a', 'b1.o', 'b2.o'] )
In this question
Linking static libraries, that share another static library we know that we can not simply merge a static library into another static library, Because this may result in some symbol problems.
Now I want to solve this problem in this way:
First get the object file of 'liba.a'. Then merge this object files with new object files to generate the final 'libb.a'.
But I found I can not find a method or function to get the object files in a static library with scons.
Can anyone help me ?
Sounds like you just want to use the same object files for 2 different libraries.
You could do something like this:
env = Environment()
env.StaticLibrary('a', ['a1.o', 'a2.o'])
env.StaticLibrary('b', ['b1.o', 'b2.o', 'a1.o', 'a2.o'])
Additionally, instead of dealing with the Object files, you could directly specify the source files. In this case, SCons will only compile the source files once, as needed.
env.StaticLibrary('a', ['a1.c', 'a2.c'])
env.StaticLibrary('b', ['b1.c', 'b2.c', 'a1.c', 'a2.c'])
Also, remember that each SCons builder returns a list of targets (each being a SCons Node). The list may have one or several entries. So, for example, the following target variable will contain the library target, and all of the objects built:
target = env.StaticLibrary('a', ['a1.c', 'a2.c'])
for t in target: print str(t)

xcode 4.6 symbol visibility

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.

Resources