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.
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:
In this case, the linker is saying " I am looking for a function defined like this:
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 functionspeccud
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: "
so if you change the prototype to:
and the function definition to:
then everything matches.
(in C++ linkage, the actual matching process is based on the mangled name, which is this:
but the error reporting process also demangles that for us:
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.)