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.
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)));
Related
I declared the the following class:
#pragma once
#include <stdio.h>
#include <vector>
#include <string>
namespace util
{
class FileReader
{
public:
FileReader();
~FileReader();
bool open(const std::wstring& name);
void close();
bool read(std::vector<char>& buf, __int64 startFrom, int size);
__int64 size() const;
private:
FILE* m_file;
std::wstring m_name;
__int64 m_size;
};
}
And its implementation:
#include "FileReader.hpp"
namespace util
{
bool FileReader::open(const std::wstring& name)
{
if (!name.empty() && (m_name != name))
{
close();
if (_wfopen_s(&m_file, name.c_str(), L"rb") == 0)
{
m_name = name;
// Get the file size
_fseeki64(m_file, 0, SEEK_END);
m_size = _ftelli64(m_file);
rewind(m_file);
}
else
{
m_file = NULL;
}
}
return (m_file != NULL);
}
// ....
}
in a seperate library and use it like this:
FileTransfer.cpp
#include <util/FileReader.hpp>
// .....
if (!m_fileReader.open(m_localFileName)) // std::wstring m_localFileName;
{
::MessageBoxA(NULL, "Failed to open file", "Error", MB_ICONERROR);
stopFileTransmission();
return;
}
in another project. Both projects compile successfully, but the FileTransfer.obj fails to link:
Error 2 error LNK2019: unresolved external symbol "public: bool
__thiscall util::FileReader::open(class std::basic_string,class
std::allocator > const &)"
(?open#FileReader#util##QAE_NABV?$basic_string#GU?$char_traits#G#std##V?$allocator#G#2##std###Z)
referenced in function
__catch$?onRequestDirClicked#FileTransferWindow##AAEXXZ$0 C:\Users\x\Documents\dev\Server\FileTransfer.obj Server
I remember it was working when I used std::string, so I assume it has something todo with std::wstring.
Any idea what could be the issue?
It seems, the problem was that the two projects had different values for the setting
Treat wchar_t as built-in type
Setting it to No (/Zc:wchar_t-) for both projects, solved the linker error. I still don't really know what the consequences will be though.
try using extern "C" to declare the open function.
I have following class inside dll
header
class __declspec(dllexport) MyClass
{
public:
bool fun1(const CString& csFilename, int& nFileID );
bool fun2(int nFileID, int nImageNum, int nStartIndex);
};
cpp
bool MyClass::fun1(const CString& csFilename, int& nFileID )
{
}
bool Myclass::fun2(int nFileID, int nImageNum, int nStartIndex)
{
}
main
void main()
{
MyClass *p = new MyClass;
p->fun1(...); //if I comment this code compiles and builds
p->fun2(...); //this is ok
}
I am getting error LNK2019: unresolved external symbol "public: bool __thiscall...
only for fun1 not for fun2 even both are in same class why ?
thanks in advance.
I am not sure what is wrong here as it works after I replace CString with std string but I am not able to reproduce same error in another small example.
# admin I think this thread should be deleted as i am not able to reproduce it.
In such form...
#ifndef UNICODE
#define UNICODE
#endif
#include <Windows.h>
#include <iostream>
class A
{
public:
void makeFoo(TCHAR* output)
{
wcscpy(outputBuffer,TEXT("Hello world ♥"));
}
private:
static const int MAX_OUTPUT_SIZE=2000;
static TCHAR outputBuffer[MAX_OUTPUT_SIZE];
};
int main()
{
TCHAR string[255];
A example;
example.makeFoo(string);
MessageBox(0,string,0,0);
system("Pause");
return 0;
}
... we have a
linking error!
1>main.obj : error LNK2001: unresolved external symbol "private:
static wchar_t * A::outputBuffer" (?outputBuffer#A##0PA_WA)
The linker error occurs because you have not provided a definition for the A::outputBuffer anywhere. Fix this by writing this in file scope:
TCHAR A::outputBuffer[A::MAX_OUTPUT_SIZE];
The value of string is unexpected because that buffer is uninitialized; makeFoo does nothing with its argument, and you do not initialize the buffer manually. Therefore it can contain anything at all ("garbage").
Add:
TCHAR A::outputBuffer[A::MAX_OUTPUT_SIZE];
above main().
I have the following project files:
//connections.cpp
#include "stdafx.h"
#include "LibraryHeaders.h"
#include "FileManager.h"
#define WSAVersion 0x202
#define GSMsgID 0x100
extern HWND Main_hWnd;
bool InitConnections ()
{
FileManager::ConnectFile *connectfile = FileManager::ReadConnectFile(connectfile);
SockBase GSConnection(WSAVersion, TCP, connectfile->GS_IP, connectfile->GS_Port, Main_hWnd, GSMsgID);
if (GSConnection.Connect() != true) {return false;}
return true;
}
//FileManager.cpp
#include "stdafx.h"
#include "FileManager.h"
#include "LibraryHeaders.h"
using namespace FileManager;
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct)
{
FileLibrary connectfile("DMOConnection.cfg");
if (connectfile.OpenFile(HEAP, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, PAGE_READWRITE) != true) {return false;}
ConnectStruct->GS_IP = connectfile.parser->str_GetToken((char*)connectfile.FileBuff);
if (ConnectStruct->GS_IP == (const char*) -1) {return false;}
ConnectStruct->GS_Port = connectfile.parser->int_GetToken((char*)connectfile.FileBuff);
if (ConnectStruct->GS_Port == -1) {return false;}
return ConnectStruct;
}
//FileManager.h
namespace FileManager
{
struct ConnectFile
{
const char* GS_IP;
unsigned int GS_Port;
};
ConnectFile* ReadConnectFile(ConnectFile*);
}
And when trying to build the project i got this error:
Connections.obj : error LNK2019: unresolved external symbol "struct FileManager::ConnectFile * __cdecl FileManager::ReadConnectFile(struct FileManager::ConnectFile *)" (?ReadConnectFile#FileManager##YAPAUConnectFile#1#PAU21##Z) referenced in function "bool __cdecl InitConnections(void)" (?InitConnections##YA_NXZ)
I dont understand why, the linker should look up and see that ive defined FileManager::ReadConnectFile on FileManager.cpp but it doesnt, any tip how to fix this?
You're defining a free function:
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct)
not a member:
ConnectFile* FileManager::ReadConnectFile(ConnectFile *ConnectStruct)
Totally different.
Also:
using namespace FileManager;
and
error LNK2019: unresolved external symbol "struct FileManager::ConnectFile [...]
suggests you have a namespace FileManager and a struct FileManager... any reason for using the same name?
i fixed it by declaring the function out of the namespace:
namespace FileManager
{
struct ConnectFile
{
const char* GS_IP;
unsigned int GS_Port;
};
}
using namespace FileManager;
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct);
The IDE is VC11 Beta, thanks for the answers.
The code
using namespace FileManager;
ConnectFile* ReadConnectFile(ConnectFile *ConnectStruct)
{ ...some definition...}
defines the ReadConnectFile function not in the namespace FileManager, but in global namespace.
Sorry for my bad English. I have 2 projects. Project 1 is a MFC dll that contains class CMyContainer, class CEmployee. Project 2 is my main project. In project 2, I created an instance of CMyContainer of type CEmployee. Now I want to sort the container but I got an error
"error LNK2019: unresolved external symbol "bool __cdecl MyComparer(class CEmployee *,class CEmployee *)" (?MyComparer##YA_NPAVCEmployee##0#Z) referenced in function "public: void __thiscall CMyContainer<class CEmployee>::sortContainer(void)" (?sortContainer#?$CMyContainer#VCEmployee####QAEXXZ)"
How can I fix this problem?
// file MyContainer.h in project 1
#include <vector>
template <class T>
class _declspec(dllexport) CMyContainer
{
public:
CMyContainer(void);
~CMyContainer(void);
...
void sortContainer();
private:
std::vector<T*> items;
typename std::vector<T*>::iterator it;
};
template <class T> void CMyContainer<T>::sortContainer()
{
typedef bool (*comparer_t)(T*,T*);
comparer_t cmp = &MyComparer;
std::sort(items.begin(), items.end(), cmp);
}
//File Employee.h in project 1
#include "MyContainer.h"
class _declspec(dllexport) CEmployee
{
public:
CEmployee(void);
~CEmployee(void);
void setEmployeeCode(CString);
CString getEmployeeCode();
friend bool MyComparer(CEmployee*, CEmployee*);
private:
CString m_szEmployeeCode;
}
//File Employee.cpp in project 1
void CEmployee::setEmployeeCode(CString val){
m_szEmployeeCode= val;
}
CString CEmployee::getEmployeeCode(){
return m_szEmployeeCode;
}
bool MyComparer(CEmployee*pEmp1, CEmployee*pEmp2)
{
return (pEmp1->getEmployeeCode().Compare(pEmp2->getEmployeeCode())<0);
}
//File main.cpp in project 2
#include <..\Models\MyContainer.h>
#include <..\Models\Employee.h>
...
CMyContainer<CEmployee> *pListEmployee;
... // insert into pListEmployee
// sort pListEmployee
pListEmployee.sortContainer();//-> This command cause error
Try to export MyComparer from the .dll with _declspec(dllexport)