Linker error 2019 while linking Winusb application and CUDA

418 views Asked by At

I have two application Winusb and coping the data from cpu to GPU using CUDA. Both work fine as two separate projects, but when I try to combine them as one project I get the following linking error.

Build Log :

1>------ Build started: Project: USB Application2, Configuration: Win7 Debug Win32 ------
1>  Compiling CUDA source file function.cu...
1>  
1>  C:\Users\bel1\documents\visual studio 2012\Projects\USB Application2\USB Application2>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\bin\nvcc.exe" -gencode=arch=compute_10,code=sm_10 --use-local-env --cl-version 2010 -ccbin "C:\Program Files\Microsoft Visual Studio 11.0\VC\bin"  -IWin7Debug\ -IWin7Debug\ -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include"     --keep-dir Win7Debug -maxrregcount=0  --machine 32 -cuda -cudart static     -D_X86_=1 -Di386=1 -DSTD_CALL -DWIN32_LEAN_AND_MEAN=1 -D_WIN32_WINNT=0x0601 -DWINVER=0x0601 -DWINNT=1 -DNTDDI_VERSION=0x06010000 -DDBG=1 -D_AFXDLL -Xcompiler "/EHsc /W0 /nologo /Od /Zi /RTC1 /MT  " -o Win7Debug\function.cu.obj "C:\Users\bel1\documents\visual studio 2012\Projects\USB Application2\USB Application2\function.cu" 
1>  Compiling CUDA source file wrapper.cu...
1>  
1>  C:\Users\bel1\documents\visual studio 2012\Projects\USB Application2\USB Application2>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\bin\nvcc.exe" -gencode=arch=compute_10,code=sm_10 --use-local-env --cl-version 2010 -ccbin "C:\Program Files\Microsoft Visual Studio 11.0\VC\bin"  -IWin7Debug\ -IWin7Debug\ -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include"     --keep-dir Win7Debug -maxrregcount=0  --machine 32 -cuda -cudart static     -D_X86_=1 -Di386=1 -DSTD_CALL -DWIN32_LEAN_AND_MEAN=1 -D_WIN32_WINNT=0x0601 -DWINVER=0x0601 -DWINNT=1 -DNTDDI_VERSION=0x06010000 -DDBG=1 -D_AFXDLL -Xcompiler "/EHsc /W0 /nologo /Od /Zi /RTC1 /MT  " -o Win7Debug\wrapper.cu.obj "C:\Users\bel1\documents\visual studio 2012\Projects\USB Application2\USB Application2\wrapper.cu" 
1>main.obj : error LNK2019: unresolved external symbol "short * __stdcall speccud(short * const)" (?speccud@@YGPAFQAF@Z) referenced in function _main
1>C:\Users\bel1\documents\visual studio 2012\Projects\USB     Application2\Win7Debug\USBApplication2.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Main.cpp

 #include "pch.h"
 short *speccud(short ispecbu[]);

 LONG __cdecl _tmain(LONG  Argc, LPTSTR ** Argv )
 //int main(int argc, char **argv)
 {  
FILE *output_file1 = fopen("output_file2.txt", "w");
FILE *output_file2 = fopen("output_file3.txt", "w");
DEVICE_DATA           deviceData;
HRESULT               hr;
USB_DEVICE_DESCRIPTOR deviceDesc;
BOOL                  bResult;
BOOL                  noDevice;
ULONG                 lengthReceived;
BOOL wrResult = TRUE;
BOOL wr1Result = TRUE;
BOOL RQResult = 0;
UNREFERENCED_PARAMETER(Argc);
UNREFERENCED_PARAMETER(Argv);


//////////////////////Open device ///////////////
hr = OpenDevice(&deviceData, &noDevice);
if (FAILED(hr)) {
    if (noDevice) {
        printf(_T("Device not connected or driver not installed\n"));
    } else {
       printf(_T("Failed looking for device, HRESULT 0x%x\n"), hr);
    }
    std::getchar();
    return 0;
}

/////////////////////Get descriptor//////////////////
bResult = WinUsb_GetDescriptor(deviceData.WinusbHandle,
                               USB_DEVICE_DESCRIPTOR_TYPE,
                               0,
                               0,
                               (PBYTE) &deviceDesc,
                               sizeof(deviceDesc),
                               &lengthReceived);
   if (FALSE == bResult || lengthReceived != sizeof(deviceDesc)) {

    printf(_T("Error among LastError %d or lengthReceived %d\n"),
           FALSE == bResult ? GetLastError() : 0,
           lengthReceived);
    CloseDevice(&deviceData);
    return 0;
}

bool sResult = FALSE;bool syResult;
bool sResult1 = FALSE;bool syResult1;
//Initialize
UCHAR Intialize[] = {0x01};
ULONG cbISize = strlen((char*)Intialize);
ULONG InSent = 0;
wrResult = WinUsb_WritePipe(deviceData.WinusbHandle, 0x01, Intialize, 1, &InSent, 0);
//Integration time - 700ms
UCHAR Inttime[] = {0x0200100000};
ULONG cbITSize = strlen((char*)Inttime);
ULONG InttimeSent = 0;
wrResult = WinUsb_WritePipe(deviceData.WinusbHandle, 0x01, Inttime, 5, &InttimeSent, 0);
//strobe signal
UCHAR strobe1[] = {0x030001};
ULONG strobeSize1 = strlen((char*)strobe1);
ULONG strobeSent1 = 0;
wr1Result = WinUsb_WritePipe(deviceData.WinusbHandle, 0x01, strobe1, 3, &strobeSent1, 0);
//Request spectra
UCHAR Rqspectra[] = {0x09};
ULONG RqSize = strlen((char*)Rqspectra);
ULONG RqSent = 0;
RQResult = WinUsb_WritePipe(deviceData.WinusbHandle, 0x01, Rqspectra,1, &RqSent, 0);
//Pixel Values
UCHAR szBuffer[15][512];
UCHAR sz1Buffer[1];
UCHAR tBuffer[1];
ULONG tReadx;
ULONG cbReadx[16];
USHORT newbuf[15][512];
short specbu[7860];
short *fans;
for (int i=0;i<16;i++)
{
    if (i<4)
    {
        sResult = WinUsb_ReadPipe(deviceData.WinusbHandle,  0x86, szBuffer[i], 512, &cbReadx[i], 0);
    }
    else if (i>=4 && i<15)
    {
        sResult = WinUsb_ReadPipe(deviceData.WinusbHandle,  0x82, szBuffer[i], 512, &cbReadx[i], 0);
    }
    else if (i = 15)
    {
        syResult = WinUsb_ReadPipe(deviceData.WinusbHandle,  0x82, sz1Buffer, 1, &cbReadx[i], 0);
    }

}
int pon=0;
for (int k=0;k<15;k++)
{
for (int l=0;l<512;l+=2)
{
    newbuf[k][l] = (szBuffer[k][(l+1)]<<8|szBuffer[k][l]);
    specbu[pon]= (szBuffer[k][(l+1)]<<8|szBuffer[k][l]);
    fprintf(output_file1,"%d\t\n",specbu[pon]);
    pon++;

}
}
//printf("%d",sizeof(specbu));
//short ARR[5] = {1,2,3,4,5}; 
//fans=speccud(ARR);
fans = speccud(specbu);
for (int k=0;k<5;k++)
{printf("%d", fans[k]);
    //fprintf(output_file2,"%d\t\n",fans[k]);
    //tempc[k]=specbu[k];
}
std::getchar();
CloseDevice(&deviceData);
return 0;
}

Wrapper.cu

#include "cuda_runtime.h"
#include <cuda.h>
#include <cstdio>
#include "device_launch_parameters.h"


__global__ void saxpy(int cn, short ca, short *cx, short *cy);
short *speccud(short ispecbu[])
{
  const int cN = 7680;
  short *cx,  *cd_x, *cd_y;
  static short *cy;
  cx = (short*)malloc(cN*sizeof(short));
  cy = (short*)malloc(cN*sizeof(short));
  cudaMalloc(&cd_x, cN*sizeof(short)); 
  cudaMalloc(&cd_y, cN*sizeof(short));
 for (int ci = 0; ci < cN; ci++) {
  cx[ci] = ispecbu[ci];
  //y[i] = 2.0f;
  }
 cudaMemcpy(cd_x, cx, cN*sizeof(short), cudaMemcpyHostToDevice);
 cudaMemcpy(cd_y, cy, cN*sizeof(short), cudaMemcpyHostToDevice);
 // Perform SAXPY on 1M elements
 saxpy<<<(cN+255)/256, 256>>>(cN, 1, cd_x, cd_y);
 cudaMemcpy(cy, cd_y, cN*sizeof(short), cudaMemcpyDeviceToHost);
 return cy;
 }

Function.cu

#ifndef __Kernel_CU__  
#define __Kernel_CU__  
 __global__ void saxpy(int cn, short ca, short *cx, short *cy)
{
 int ci = blockIdx.x*blockDim.x + threadIdx.x;
  cy[ci] = ca+cx[ci];
}

#endif

I also have a device.cpp which has the function of opendevice, closedevice, etc(part of the Winusb and has too many lines of auto generated code). It looks like some sort of linker error between Cuda and Winusb application. when I simply create two visual studio project one for Cuda and other for winusb both works perfectly.

1

There are 1 answers

2
Robert Crovella On BEST ANSWER

The linker looks at the symbols that are required by main.cpp (i.e. that are entry points needed by main.obj), and tries to find definitions for those entry points in other modules in your project.

In the case of main.obj, there was one symbol (entry point) that it could not find defined elsewhere:

1>main.obj : error LNK2019: unresolved external symbol "short * __stdcall speccud(short * const)" (?speccud@@YGPAFQAF@Z) referenced in function _main

In this case, the linker is saying " I am looking for a function defined like this:

short * __stdcall speccud(short * const)

but I can't find it!".

Of course, you didn't decorate your prototype in main.cpp with __stdcall, that was done automatically by the compiler, before it decided what symbol is needed externally. The VS C++ compiler can behave in a large variety of ways, and in this case its behavior when compiling your main.cpp file was different than its (decorating) behavior when compiling Wrapper.cu. As a result, the function speccud in Wrapper.cu was getting exported with a different name than what was identified as needed by main.obj, so the linker was unable to match them.

Therefore, if you avoid this mixup by causing the function in Wrapper.cu to get exported in a fashion that exactly matches what the linker says it is looking for in main.obj, then the linker can find the match:

The linker said, " I'm looking for: "

    short * __stdcall speccud(short * const)

so if you change the prototype to:

    short * __stdcall speccud(short * const);

and the function definition to:

    short * __stdcall speccud(short * const ispecbu)

then everything matches.

(in C++ linkage, the actual matching process is based on the mangled name, which is this:

?speccud@@YGPAFQAF@Z

but the error reporting process also demangles that for us:

short * __stdcall speccud(short * const)

mangling/demangling follows a defined procedure, so you can use an online demangling service to convert the mangled name to it's demangled version. The mangled version of this function would look different if the function did not have the __stdcall decoration.)