Search code examples
c++windowsdllunresolved-externalmost-vexing-parse

Bizarre unresolved external compiling DLL


I am trying to follow the instructions on this site: http://support.microsoft.com/kb/q168958

Here is the code:

#include <windows.h>
#include <malloc.h>

namespace Test {

template<class TYPE> class TestBuffer
{
  private:
    TYPE*   m_pData;
    size_t  m_uSize;

  public:
    TestBuffer(size_t uSize) : m_pData(NULL), m_uSize(0)
    {
      m_pData = (TYPE*)malloc(uSize * sizeof(TYPE));
    }

    ~TestBuffer() { if (NULL != m_pData) free(m_pData); }

  public:
    bool IsValid() const { return NULL != m_pData; }
    operator TYPE*() const { return m_pData; }
};

template class __declspec(dllexport) Test::TestBuffer<wchar_t>;

__declspec(dllexport) bool GetCurrentDir(char* szDir, size_t uSize)
{
  DWORD dwRequiredSize = ::GetCurrentDirectoryW(0, NULL);
  Test::TestBuffer<wchar_t> wideCharBuffer(size_t(dwRequiredSize));

  bool bResult = (dwRequiredSize - 1 == 
    ::GetCurrentDirectoryW(dwRequiredSize, (wchar_t*)wideCharBuffer));

  wcstombs(szDir, (wchar_t*)wideCharBuffer, uSize);

  return bResult;
}

} // namespace Test

BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
  char szPath[MAX_PATH] = { 0 };
  Test::GetCurrentDir(szPath, MAX_PATH);

  return TRUE;
}

Putting this in a WIN32 DLL project in VS spits out the following error:

error LNK2019: unresolved external symbol "class Test::TestBuffer<wchar_t> __cdecl wideCharBuffer(unsigned int)" (?wideCharBuffer@@YA?AV?$TestBuffer@_W@Test@@I@Z) referenced in function "bool __cdecl Test::GetCurrentDir(char *,unsigned int)"

I'm not sure why the linker can't find the definition as everything is defined right there, along with export statement for TestBuffer. Also, in the example, I shouldn't even need to export the explicit instantiation of TestBuffer as it isn't being exposed in the DLL interface, only GetCurrentDir() is.

Any guesses as to why the code isn't being generated for TestBuffer so the linker can find it?

P.S. This is a contrived example to demonstrate the problem, not actual production code.


Solution

  • The compiler see the declaration of wideCharBuffer as a function declaration (most vexing parse). Try changing it to:

    Test::TestBuffer<wchar_t> wideCharBuffer((size_t(dwRequiredSize)));