Qt: access to external function from another subproject - c++

I have a Qt project with 3 subprojects: Irrad (app), RadBase (app) and RadLib (library). All these subprojects should use a function QString secstointerval(qint64) making a string (days, hours, seconds) from an interval in seconds. I've inserted this function into one of source files in RadLib and it is accessed within this subproject without problems when announcing it as external QString secstointerval(qint64 t).
But when I'm trying to access it from RadBase and Irrad, I'm getting an unresolved external error. Is there a way to use this function in all subprojects, or should I create a class for this function?

Related

What / where is __scrt_common_main_seh?

A third party library in my program is trying to call __scrt_common_main_seh by way of the Microsoft library msvcrt.lib, but is defined by some unknown library and therefore gives a linker error. I don't know what this function is supposed to do or where it is defined.
I looked online for this function, but did not find any clues except for general descriptions of what linker errors are.
I believe it might be doing some setup for win32 GUI applications. The library which defines it might be configured as project dependency by Visual Studio but my project is using Bazel.
Summary
For non-console applications having error error LNK2019: unresolved external symbol main referenced in function "int __cdecl __scrt_common_main_seh(void)" try adding linker flag /ENTRY:wWinMainCRTStartup or /ENTRY:WinMainCRTStartup
For console applications having that error, make sure to implement a main() function.
Details
This answer shows that __scrt_common_main_seh is normally called during mainCRTStartup which is the default entry point for windows console applications. __scrt_common_main_seh is then (indirectly) responsible for calling main().
My program did not have a main() function, which might have prevented the compiler from generating __scrt_common_main_seh (Just speculating. I am totally clueless about who defines __scrt_common_main_seh)
I did find, however, that the library I was linking against defined a wWinMain() function. So I tried adding the linker flag /ENTRY:wWinMainCRTStartup and the linker error went away.

"Shared" linkage works on Linux, not on Windows

Given a big project, which generates an executable on both Linux and Windows architectures, I would like to take some classes (name it BigProjectClassA, BigProjectClassB and BigProjectClassC) to make a kind of plugin and modify the state of objects created from these three classes.
Hence, my tiny own project has code like this:
class TinyProjectExampleClass
{
void modifyA(BigProjectClassA& a) {(...)}
void modifyB(BigProjectClassB& b) {(...)}
void modifyC(BigProjectClassC& c) {(...)}
(...)
};
I'm building this code in order to generate a shared library (I'm coming from Linux background, so I don't know if this is the proper term for a DLL) which will be used within the big project.
When I try to build this on Linux, it is not necessary to link this code against the BigProjectClasses' object code and the big project gets correctly the expected state; however, Windows MSVC2013 linker complains with this error:
error LNK2001: unresolved external symbol "public: void __cdecl BigProjectClassX (...)"
How can I sort this out?

C++ Unit Test Native C++

First, a little background:
At work, I've inherited a large C++ program (a language I haven't used extensively in 12 years). To help myself better understand the application and how it fits together, I thought, "I love TDD, why not write some unit tests!". I've since spent two days getting a simple unit test to compile. I'm at the point where it gets to the linker, but I get the following error:
CIniReader* reader = new CIniReader("");
Error 3 error LNK2019: unresolved external symbol "public: __thiscall CIniReader::CIniReader(char *)" (??0CIniReader##$$FQAE#PAD#Z) referenced in function "public: void __clrcall ApogeeTests::UnitTest1::TestMethod1(void)" (?TestMethod1#UnitTest1#ApogeeTests##$$FQ$AAMXXZ) C:\Users\champad\Documents\Applications\Leading Hedge\src\Apogee.Tests\UnitTest1.obj Apogee.Tests
Now, I can resolve this buy setting the project that this lives in to a static library, rather than a DLL project (Properties -> Configuration Properties -> General -> Configuration Type).
My question is this: MUST I do this? It seems there has to be a way for the linker to identify the functions it needs at compile time without having to constantly switch all 24 projects to lib when I want to unit test, and back when I need to deploy it.
Any thoughts?
While not exactly what I was looking for, this is what I'm doing unless anyone has a better suggestion!
I added a new project configuration and called it UnitTesting. Under that configuration, all the C++ projects are static libraries that the unit test project can reference. I figure I change the configuration before deploying, so this would be easy for me to remember.
While not ideal, this is working. But if there is a better way, please let me know!
Visual Studio creates a static library for each DLL you create, specifically for linking with client code.
If your project has the following modules:
core-functionality.dll
unit-tests.exe
Then your unit-tests.exe will either load APIs from core-functionality.dll using LoadLibrary and family and casting the resulting function pointers to the correct types (this is ugly, error prone and difficult to maintain), or it can link statically, against core-functionality.lib (this should be generated during the build of core-functionality.dll).
I think you are looking for the second option.

Boost 1.56 with QT creator, "LNK1104: cannot open file 'libboost_unit_test_framework-vc100-mt-gd-1_56.lib'"

I am working on a project of boost unit testing framework using QT creator. I have written a small test program and trying to link libboost_unit_test_framework-vc100-mt-gd-1_56.lib. This library is present at specified path. But program fails to compile giving said linking error.
I searched on net and found that, error should go with #define BOOST_ALL_NO_LIB. But then, I am getting below error:
main.obj:-1: error: LNK2019: unresolved external symbol "class boost::unit_test::test_suite * __cdecl init_unit_test_suite(int,char * * const)" (?init_unit_test_suite##YAPAVtest_suite#unit_test#boost##HQAPAD#Z) referenced in function _main
The above function is a part of libboost_unit_test_framework-vc100-mt-gd-1_56.lib.
I have written same unit tests using VS 2010 and with the same boost libraries. The program worked properly with expected behavior.
What could be possibly going wrong with the usage of boost on QT?
You are missing the test module initialization function. Have you defined BOOST_TEST_MAIN or BOOST_TEST_MODULE before you include the UTF header?
To automatically generate an empty test module initialization function you need to define BOOST_TEST_MAIN before including the boost/test/unit_test.hpp header. The value of this define is ignored. Alternatively you can define the macro BOOST_TEST_MODULE to be equal to any string (not necessarily in quotes). This macro causes the same result as BOOST_TEST_MAIN, and in addition the macro value becomes the name of the master test suite.
For a test module consisting of multiple source files you have to define these flags in a single test file only. Otherwise you end up with multiple instances of the initialization function.
More info here: http://www.boost.org/doc/libs/1_57_0/libs/test/doc/html/utf/user-guide/initialization.html

Getting "error LNK2001: unresolved external symbol _gnutls_free" when using GnuTLS 3.1.6 from Visual Studio 2012

I am attempting to build a project in Visual Studio 2012 that uses GnuTLS. I downloaded the latest official Windows build from the website, and created a link library by running lib /def:libgnutls-28.def in the bin directory form a Visual Studio command prompt.
After adding a typedef long ssize_t, the code compiles fine, but linking fails with the following error:
source_file.obj : error LNK2001: unresolved external symbol _gnutls_free
C:\Path\to\executable.exe : fatal error LNK1120: 1 unresolved externals
I am calling gnutls_free to free some memory allocated and returned by the library. If I remove the call to gnutls_free, the project links successfully. Given that gnutls_free is just a global variable (containing a function pointer) exported by the library, I'm not sure why accessing it results in an unresolved reference to a different symbol. I have verified that gnutls_free is not #defineed to anything.
As a test, I tried doing gnutls_free_function test = gnutls_free; which also resulting in the link error. Running grep -w -r _gnutls_free . on the GnuTLS source code returns nothing, so I am at a loss.
Any ideas for getting this working would be greatly appreciated.
EDIT:
Adding __declspec(dllimport) to the declaration of gnutls_free in gnutls.h allows the link to succeed. Is there any way to accomplish this without maintaining a custom version of the header file?
There doesn't seem to be a way to have the linker or import library automatically dereference the IAT's pointer to the data item the same way that is done for functions (via a small trampoline function that is statically linked into the module importing the function). The __declspec(dllimport) attribute tells that compiler that this dereferencing needs to be done so it can insert code to perform the dereferencing of the IAT pointer implicitly. This allows exported data to be accessed and for functions allows the compiler to call the imported function via an indirect call through the IAT pointer rather than by calling the trampoline function.
See a couple of Raymond Chen's articles about dllimport for a good explanation of what goes on for function calls (he didn't discuss importing data, unfortunately):
Calling an imported function, the naive way
How a less naive compiler calls an imported function
The MS linker or import library doesn't have a mechanism to help the compiler get imported data in a 'naive' way - the compiler needs the the __delcspec(dllimport) hint that an extra dereference through the IAT is needed. Anyway, the point of all this is that it seems there's no way to import data except by using the __declspec(dllimport) attribute.
If you want to avoid modifying the gnutls distribution (which I can understand), here's one rather imperfect workaround:
You can create a small object file that contains nothing but a simple wrapper for gnutls_free(); since gnutls_free() has an interface with no real dependencies, you can have the necessary declarations 'hardcoded' instead of including gnutls.h:
typedef void (*gnutls_free_function) (void *);
__declspec(dllimport) extern gnutls_free_function gnutls_free;
void xgnutls_free(void* p)
{
gnutls_free(p);
}
Have your code call xgnutls_free() instead of gnutls_free().
Not a great solution - it requires your code to call a wrapper (so it's particularly not great if you'll be incorporating 3rd party code that might depend on gnutls_free()), but it might be good enough.