错误LNK2019:未解析的外部符号(小型库)

时间:2016-06-28 19:47:22

标签: c++-cli visual-studio-2005 clr

我在VS2005中创建了一个小型CLR库(MyClient),将线程集成到现有的C ++应用程序中(也用VS2005编写)。当我构建项目时会出现以下错误:

1>PSR_CRSDlg.obj : error LNK2019: unresolved external symbol "public: static void __cdecl MyClient::StartClientThread(void)" (?StartClientThread@MyClient@@SAXXZ) referenced in function "public: void __thiscall CPSR_CRSDlg::OnBnClickedInit2(void)" (?OnBnClickedInit2@CPSR_CRSDlg@@QAEXXZ)
1>PSR_CRSDlg.obj : error LNK2019: unresolved external symbol "public: static void __cdecl MyClient::SendJointValues(double *)" (?SendJointValues@MyClient@@SAXPAN@Z) referenced in function "public: void __thiscall CPSR_CRSDlg::OnTimer(unsigned int)" (?OnTimer@CPSR_CRSDlg@@QAEXI@Z)
1>PSR_CRSDlg.obj : error LNK2019: unresolved external symbol "public: static void __cdecl MyClient::StopConnection(void)" (?StopConnection@MyClient@@SAXXZ) referenced in function "public: void __thiscall CPSR_CRSDlg::OnBnClickedMovepenall(void)" (?OnBnClickedMovepenall@CPSR_CRSDlg@@QAEXXZ)
1>D:\Desktop\PSR\Software\Source - June 21\PSR_CRS_SVN - Copy (2)\Debug\PSR_CRS.exe : fatal error LNK1120: 3 unresolved externals

我是C ++和OOP的新手,但过去几周一直在不断进行。这是我的.h文件:

using namespace std;
class MyClient
{
public:
    static char* createMsg(string s);
    static char* parseJSON(double j1, double j2, double j3, double j4, double j5, double j6);
    static void StartConnection();
    static void StartClientThread();
    static void StopConnection();
    static void SendJointValues(double *joints);
};

我的.cpp文件只是将函数实例化为char * MyClient :: createMsg(string s)等,所以我不认为这是问题所在。我还浏览了大部分链接here并进行了大量搜索,以确保我的库全部存在,没有循环的lib依赖,库顺序等。在我的整个解决方案中的3个项目中,2个使用“没有公共语言运行时支持”但我的客户端库使用“公共语言运行时支持”,这是库之间的一个区别。

有没有人想过为什么会出现这些错误?

完整客户端库:

#define WIN32_LEAN_AND_MEAN
#define NOMINMAX

#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <iostream>
#include <typeinfo>
#include <sstream>
#include "Client.h"

using namespace std;
using namespace System;
using namespace System::Threading;

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#define DEFAULT_BUFLEN 4096
#define DEFAULT_PORT "9001"


char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
SOCKET ConnectSocket;

char* MyClient::createMsg(string s) {
    char *a = new char[s.size() + 1];
    a[s.size()] = 0;
    memcpy(a, s.c_str(), s.size());
    return a;
}

char* MyClient::parseJSON(double j1, double j2, double j3, double j4, double j5, double j6)
{
    ostringstream oss;
    oss << j1 << ',' << j2 << ',' << j3 << ',' << j4 << ',' << j5 << ',' << j6;
    string joints = oss.str();
    return createMsg(joints);
}

void MyClient::StartConnection() 
{
    //printf("Connection Starting... \n");
    WSADATA wsaData;
    ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL,
                    *ptr = NULL,
                    hints;

    int argc = 2;

    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s server-name\n", "client");
        return;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    //iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return;
    }

    // Attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return;
        }

        // Connect to server.
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return;
    }
    return;
}

void MyClient::StopConnection(){
    closesocket(ConnectSocket);
    WSACleanup();
    return;
}

void MyClient::SendJointValues(double *joints){
    char *j;
    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    j = parseJSON(joints[0],joints[1],joints[2],joints[3], \
        joints[4],joints[5]);
    int x = send(ConnectSocket, j, strlen(j), 0);
    //iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
}

void MyClient::StartClientThread()
{
    Thread^ cln;
    ThreadStart ^ClientThread = gcnew ThreadStart(&MyClient::StartConnection);
    cln = gcnew Thread(ClientThread);
    cln->IsBackground = true;
    cln->Start();
}

编辑:当我创建虚拟应用程序与我正在尝试集成的应用程序相同的设置时,没有发生这些错误,这就是为什么我不确定发生了什么变化或如何解决错误。

2 个答案:

答案 0 :(得分:0)

我想也许您在EXE中包含了库中的头文件。

在C ++ / CLI中编写库时,它使用.Net机制导出类。你不需要一个头文件来声明这个类,.Net元数据可以解决这个问题。

只需确保您的EXE已将库添加为.Net参考,然后继续使用库类。

答案 1 :(得分:0)

所以我不确定这个特定错误的确切原因是什么,但总的来说我发现由于原始应用程序使用/ MTd运行时库和使用我的新库而遇到了很多麻烦/ MD