Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you properly link to a static library using g++

Solution: Thanks to everyone who commented on this issue, but I resolved it on another forum, and figured I would post the answer here for anybody having the same issue.

So, I guess only dynamic libraries make use of __declspec(dllexport), so when you try to create a static library, the methods are exported (an the names need to be mangled to be c++ compatible), so when declaring extern "C" __declspec.... you end up with method names that aren't recognized when trying to link statically.

So, simple fix.....remove the __declspec

I have 2 projects, one is a static library, the other is just a win32 application.

I simply want to include the library I've created into my win32 application, however g++ keeps giving me this error:

../MyLib/TestClass.h:16: undefined reference to `imp__ZTV9TestClass'

That is the error I get when trying to compile the application, even though that file is part of the library.

I have attempted to create the most simplified version of this project as possible in an attempt to find the error.

Here are the source files for both projects:

MyLib.h - This is the main include file for clients to reference functions in the library

#ifndef MYLIB_H
#define MYLIB_H

#include "libexport.h"
#include "TestClass.h"

#endif  /* MYLIB_H */

libexport.h - Pretty generic file to define import/export keywords

#ifndef LIBEXPORT_H
#define LIBEXPORT_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef LIB
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
}
#endif

#endif  /* LIBEXPORT_H */

TestClass.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include "libexport.h"

class DLL_EXPORT TestClass
{
public:
    TestClass() {};
    virtual ~TestClass() {};

    void TestFunc();
};

#endif  /* TESTCLASS_H */

TestClass.cpp

#define LIB

#include <stdio.h>
#include "TestClass.h"

void TestClass::TestFunc()
{
    printf("This function was called from within the library.\n");
}

And lastly, the win32 application that implements the library:

Main.cpp

#include <windows.h>
#include "../MyLib/MyLib.h"

#pragma comment(lib, "libmylib.a")

int __stdcall WinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPSTR lpCmdLine,
                      int nCmdShow)
{

    TestClass *myClass = new TestClass();

    delete myClass;
    myClass = 0;

    return 0;
}

The library compiles with no errors, however, here is the output when compiling the main application:

g++.exe    -c -g -MMD -MP -MF build/Debug/MinGW-Windows/main.o.d -o build/Debug/MinGW-Windows/main.o main.cpp
mkdir -p dist/Debug/MinGW-Windows
g++.exe     -mwindows -o dist/Debug/MinGW-Windows/testclient build/Debug/MinGW-Windows/main.o -L../MyLib/dist/Debug/MinGW-Windows -lmylib 
build/Debug/MinGW-Windows/main.o: In function `TestClass':
C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:16: undefined reference to `_imp___ZTV9TestClass'
make[2]: Leaving directory `/c/Users/Nick/Documents/NetBeansProjects/TestClient'
build/Debug/MinGW-Windows/main.o: In function `~TestClass':
make[1]: Leaving directory `/c/Users/Nick/Documents/NetBeansProjects/TestClient'
C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:17: undefined reference to `_imp___ZTV9TestClass'
collect2: ld returned 1 exit status
make[2]: *** [dist/Debug/MinGW-Windows/testclient.exe] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2


BUILD FAILED (exit value 2, total time: 1s)

Most of the other posts I've seen regarding this topic say that the problem lies in the linking order, but even after adding -lmylib to the beginning of the compiler build line, the same errors persist:

g++.exe -lmylib -mwindows -o dist/Debug/MinGW-Windows/testclient build/Debug/MinGW-Windows/main.o -L../MyLib/dist/Debug/MinGW-Windows -lmylib 
build/Debug/MinGW-Windows/main.o: In function `TestClass':
C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:16: undefined reference to `_imp___ZTV9TestClass'

I really need help on this, I've built many dynamic libraries before using the above code, and it works with no problems, I can't understand why I'm having so much trouble building a simple static library. Any help is greatly appreciated.

like image 299
DivXZero Avatar asked Jan 31 '12 11:01

DivXZero


People also ask

How do I link a static library?

Static libraries are created by copying all necessary library modules used in a program into the final executable image. The linker links static libraries as a last step in the compilation process. An executable is created by resolving external references, combining the library routines with program code.

What happens when you link a static library?

Static linking increases the file size of your program, and it may increase the code size in memory if other applications, or other copies of your application, are running on the system. This option forces the linker to place the library procedures your program references into the program's object file.

How do I link a static library in Visual Studio 2015?

To create a static library project in Visual Studio 2015On the menu bar, choose File > New > Project. In the New Project dialog box, select Installed > Templates > Visual C++ > Win32. In the center pane, select Win32 Console Application. Specify a name for the project—for example, MathLibrary—in the Name box.

What does it mean to statically link a library?

In computer science, a static library or statically-linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable.


3 Answers

-L/path/to/library/ and -lName as g++ options worked for me. Do not specify the library name in the path/to/library .

like image 57
TeaOverflow Avatar answered Oct 24 '22 10:10

TeaOverflow


Solution: Thanks to everyone who commented on this issue, but I resolved it on another forum, and figured out I would post the answer here for anybody having the same issue.

So, I guess only dynamic libraries make use of __declspec(dllexport), so when you try to create a static library, the methods are exported (an the names need to be mangled to be C++ compatible), so when declaring extern "C" __declspec.... you end up with method names that aren't recognized when trying to link statically.

So, simple fix: remove the __declspec

like image 32
2 revs, 2 users 73% Avatar answered Oct 24 '22 09:10

2 revs, 2 users 73%


Try putting -L and -l before main.o in the linking command line.

like image 27
selalerer Avatar answered Oct 24 '22 10:10

selalerer