0

I've created a small CLR library (MyClient) in VS2005 to integrate threading into an existing C++ application (also written in VS2005). When I build the project get these errors:

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

I'm new a bit new to C++ and OOP but have been doing it continuously for the past few weeks. This is my .h file:

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);
};

My .cpp file just has the functions instantiated as char* MyClient::createMsg(string s), etc, so I don't think that is the problem. I've also gone through most of the links here and searched a lot to make sure my libraries were all there, no circular lib dependency, library order, etc. Out of the 3 projects in my whole solution, 2 use "No Common Language Runtime support" but my client library uses "Common Language Runtime Support", this is the one difference between the libraries.

Does anyone have thoughts on why these errors are occurring?

Full Client Library:

#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();
}

Edit: These errors did not occur when I created a dummy application when the same settings as the application I am trying to integrate with right now, which is why I'm not sure what has changed or how to resolve the errors.

Community
  • 1
  • 1
akivjh
  • 19
  • 6
  • Before somebody closes this a duplicate, did you search the internet for "lnk2019"? – Thomas Matthews Jun 28 '16 at 19:50
  • Usually the "unresolved symbol error" means you are not linking an object, library or dll file. – Thomas Matthews Jun 28 '16 at 19:52
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Thomas Matthews Jun 28 '16 at 19:53
  • @ThomasMatthews yes, i searched extensively for lnk2019 as well as lnk1120! – akivjh Jun 28 '16 at 19:53
  • @ThomasMatthews i went through that document, even said that I did in my post and linked it too – akivjh Jun 28 '16 at 19:54
  • @ThomasMatthews would you at least be able to have insight on whether the file not being linked is in the client library or the main application? – akivjh Jun 28 '16 at 20:44
  • There are tools that can search a library file or executable for strings or symbols. Use one of those. I have Cygwin loaded on my Windows systems, so I can use `find` and `grep` to search libraries for symbols. – Thomas Matthews Jun 28 '16 at 22:46

2 Answers2

0

I think perhaps you're including the header file from the library in your EXE.

When you write a library in C++/CLI, it uses the .Net mechanisms for exported classes. You don't need a header file to declare the class, the .Net metadata takes care of that.

Just make sure that your EXE has a the library added as a .Net reference, and just go ahead and use the library class.

David Yaw
  • 27,383
  • 4
  • 60
  • 93
0

So I'm not sure what the exact cause of this specific error was, but overall I found out that I was having a lot of trouble due to the original application using the /MTd runtime library and my new library using /MD

akivjh
  • 19
  • 6