11
votes

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.

3
It's a static library, so try just libmylib.a (with no -l) instead of -lmylib. You might have to specify the full path: build/Debug/libmylib.a or whatever. - TonyK
It looks like that produces the same thing: g++.exe -mwindows ../MyLib/dist/Debug/MinGW-Windows/libmylib.a -o dist/Debug/MinGW-Windows/testclient build/Debug/MinGW-Windows/main.o -L../MyLib/dist/Debug/MinGW-Windows -lmylib make[2]: Leaving directory /c/Users/Nick/Documents/NetBeansProjects/TestClient' make[1]: Leaving directory /c/Users/Nick/Documents/NetBeansProjects/TestClient' build/Debug/MinGW-Windows/main.o: In function TestClass': C:\Users\Nick\Documents\NetBeansProjects\TestClient/../MyLib/TestClass.h:16: undefined reference to _imp___ZTV9TestClass' - DivXZero
the order of linking objects and ar archives is important too - PlasmaHH
nos, it IS at the end, I simply stated that I tried it at the beginning with no new results, it helps if you look at the information provided. - DivXZero
Put ../MyLib/dist/Debug/MinGW-Windows/libmylib.a after build/Debug/MinGW-Windows/main.o. - TonyK

3 Answers

5
votes

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

3
votes

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

1
votes

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