Search code examples
c++googletest

What is GTEST_API_ in GTEST_API_ int main(int argc, char **argv) {}?


To use Google Test framework one should (?) use a main function:

GTEST_API_ int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  [...]
  return RUN_ALL_TESTS();
}

What is GTEST_API_?

In file gtest-port.h I can see something like this:

# if GTEST_LINKED_AS_SHARED_LIBRARY
#  define GTEST_API_ __declspec(dllimport)
# elif GTEST_CREATE_SHARED_LIBRARY
#  define GTEST_API_ __declspec(dllexport)
# endif
#elif __GNUC__ >= 4 || defined(__clang__)
# define GTEST_API_ __attribute__((visibility ("default")))
#endif // _MSC_VER

#ifndef GTEST_API_
# define GTEST_API_
#endif

Here's some description of __declspec: https://msdn.microsoft.com/en-us/library/dabb5z75.aspx

__declspec Visual Studio 2015 Other Versions Microsoft Specific

The extended attribute syntax for specifying storage-class information uses the __declspec keyword, which specifies that an instance of a given type is to be stored with a Microsoft-specific storage-class attribute listed below. Examples of other storage-class modifiers include the static and extern keywords. However, these keywords are part of the ANSI specification of the C and C++ languages, and as such are not covered by extended attribute syntax. The extended attribute syntax simplifies and standardizes Microsoft-specific extensions to the C and C++ languages.

Which I don't understand.

Here I have a description of C++ functions:

http://www.cplusplus.com/doc/tutorial/functions/

type name ( parameter1, parameter2, ...) { statements }

Where: - type is the type of the value returned by the function. [...]

So does GTEST_API_ changes something about the returned int?


Solution

  • The full source code is:

    #ifdef _MSC_VER
    # if GTEST_LINKED_AS_SHARED_LIBRARY
    #  define GTEST_API_ __declspec(dllimport)
    # elif GTEST_CREATE_SHARED_LIBRARY
    #  define GTEST_API_ __declspec(dllexport)
    # endif
    #elif __GNUC__ >= 4 || defined(__clang__)
    # define GTEST_API_ __attribute__((visibility ("default")))
    #endif // _MSC_VER
    
    #ifndef GTEST_API_
    # define GTEST_API_
    #endif
    

    When you build shared libary (dll in windows or shared object in Linux), by default, Microsoft Visual C++ will not export anything, we need to use IAT to find the proper function. In addition, gcc (from version 4) and clang will:

    With -fvisibility=hidden, you are telling GCC that every declaration not explicitly marked with a visibility attribute has a hidden visibility.

    It is an optimization, a hint to the compiler that the dynamic shared object is going to export the function pointer directly rather than just an entry in the IAT(Import Address Table)/GOT(Global Offset Table) of the dynamic shared object. It allows it to generate better code, saving a function pointer load from the IAT/GOT and an indirect jump.

    You can try it your self, make a dll in Windows, build it, VC++ won't create the .lib file for you, dependency walker will show that there're no exported function. I'm not sure but I heard that you can use it via a module-definition (.DEF) file, it is common to use .def file with COM.

    Hence, you need to specify GTEST_API_ to an exported function to enable its visibility

    Further reading: