0

I'm calling a class method in a shared library from within another shared library. Application builds fine on Linux and macOS but on Windows I receive:

exportlib.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: class std::vector > __cdecl Algorithmslib::k_means(class std::vector > const &,unsigned __int64,unsigned __int64)" (__imp_?k_means@Algorithmslib@@QEAA?AV?$vector@VPoint@@V?$allocator@VPoint@@@std@@@std@@AEBV23@_K1@Z) referenced in function "private: void __cdecl Exportlib::setSuppPoints(void)" (?setSuppPoints@Exportlib@@AEAAXXZ) debug\exportlib.dll : fatal error LNK1120: 1 unresolved externals

I ran out of ideas what might cause the error (only on Windows!)


Shared library with exported class:

// Project file for exported shared library
// algorithmslib.pro

DEFINES += ALGORITHMSLIB_LIBRARY

Export or import according to defines:

// algorithmslib_global.h

#if defined(ALGORITHMSLIB_LIBRARY)
#  define ALGORITHMSLIBSHARED_EXPORT Q_DECL_EXPORT
#else
#  define ALGORITHMSLIBSHARED_EXPORT Q_DECL_IMPORT
#endif

Class declaration:

// algorithmslib.h

#include "algorithmslib_global.h"

class ALGORITHMSLIBSHARED_EXPORT Algorithmslib : public QObject
{
    Q_OBJECT

public:
    Algorithmslib();
    std::vector<Point> k_means(const std::vector<Point>& data,
                               size_t k,
                               size_t number_of_iterations);
};

Calling k_means method of exported class from within another shared library:

// This is a second shared library which calls the exported class of the 1st shared library
// exportlib.cpp

#include "algorithmslib.h"

void Exportlib::setSuppPoints()
{
    Algorithmslib algorithmEngine;
    std::vector<Point> means = algorithmEngine.k_means(data, k, number_of_iterations);
}

I'm compiling with Desktop_Qt_5_12_1_MSVC2017_64bit-Debug kit:

Compilers


I renamed the shared library to something very unique, and yet the same linker error is thrown. Therefore, this issue is NOT my case

Megidd
  • 7,089
  • 6
  • 65
  • 142
  • Is `k_means` function defined? – vahancho Apr 29 '19 at 07:05
  • how do you build your application ? Build command line would be interesting. If it build on linux/mac it should as well on windows. Are you using visual studio ? – AF_cpp Apr 29 '19 at 07:18
  • @vahancho Yes, `k_means` is implemented in source code, that's why build is fine on Linux and macOS :) – Megidd Apr 29 '19 at 07:25
  • @AF_cpp I'm using Qt Creator. I have deleted the build directory and repeated the build process multiple times, but no luck :( – Megidd Apr 29 '19 at 07:26
  • @user3405291, some linkers do not complain when you call a function that has only declaration and no definition. In such cases you detect the problem only at run-time. – vahancho Apr 29 '19 at 07:34
  • This might be a problem with name mangling. Did you check if both shared libraries are compiled using the same compiler? – Annyo Apr 29 '19 at 07:45
  • Do other calls inside the same library work ? Maybe you should check the qtCreator documentation for how to specify dll dependencies. – AF_cpp Apr 29 '19 at 07:50
  • @Annyo Right. It can be something [like this bug report](https://bugreports.qt.io/browse/QTBUG-73959) – Megidd Apr 29 '19 at 08:11
  • @user3405291 Yes, it might be that, but that's not what I meant. I was talking about [that](https://stackoverflow.com/questions/1314743/what-is-name-mangling-and-how-does-it-work). Basically, name mangling is a step required for linking in C++, but different compilers do that differently, thus you can't link with a compiler against a library compiled by another compiler. – Annyo Apr 29 '19 at 08:31
  • @Annyo Thanks :) I double-checked, Qt Creator is using the same build tools for all shared libraries. – Megidd Apr 29 '19 at 09:07
  • Maybe I should have started there: did you [update your .pro file](https://stackoverflow.com/questions/7182229/linking-to-shared-library-in-qt) correctly to link against the shared library ? (I think you did, since it is compiling on Linux and MacOS, make sure the paths are correct too) – Annyo Apr 29 '19 at 09:21

1 Answers1

1

First shared lib

I have a struct inside 1st shared library:

// algorithmslib.h

struct Point {
    float x{0}, y{0}, z{0};
};

Second shared lib

I was using the above struct inside my 2nd shared library like this:

header:

// exportlib.h

class Point; // Note that I was using "class" here 
             // but the declaration inside algorithmslib.h is "struct"

size_t computeNumberOfClusters(const std::vector<Point> &data);

source:

//exportlib.cpp

#include "algorithmslib.h"

std::vector<Point> data(number_of_points); // Point structure is declared in algorithmslib.h

size_t k = computeNumberOfClusters(data);
size_t number_of_iterations = 300;
Algorithmslib algorithmEngine;

std::vector<Point> means = algorithmEngine.k_means(data, k, number_of_iterations);

Fix

I changed the header for 2nd shared library from class Point; to struct Point; and linker error on Windows got resolved:

// exportlib.h

struct Point; // declared in algorithmslib.h as "struct" NOT "class"
Community
  • 1
  • 1
Megidd
  • 7,089
  • 6
  • 65
  • 142
  • I wonder why Linux (gcc-g++) and macOS (clang++) don't care about `class` and `struct` mis-match! – Megidd May 01 '19 at 07:51