我在构建程序时遇到了一些麻烦。我正在使用 Visual Studio 2008 处理 Windows 7 professional 32 位。我有 Cuda SDK,并且我的项目设置了 cudart.lib 等的所有链接。我的问题是当我尝试构建我的项目时,它返回以下错误:
1>crowdSim.obj:错误 LNK2019: 未解析的外部符号 函数“protected: void __thiscall”中引用的_setParameters 人群::_create(int)" (?_create@Crowd@@IAEXH@Z) 1>crowdSim.obj:错误LNK2019: 未解析的外部符号 _mapBuffer 在函数“protected: void __thiscall Crowd::_create(int)" (?_create@Crowd@@IAEXH@Z) 1>crowdSim.obj:错误LNK2019: 未解析的外部符号 _allocToDevice 在函数“protected: void __thiscall”中引用 人群::_create(int)" (?_create@Crowd@@IAEXH@Z) 1>crowdSim.obj:错误LNK2019: 未解析的外部符号 _registerBuffer 在函数“protected: void __thiscall”中引用 人群::_create(int)" (?_create@Crowd@@IAEXH@Z) 1>../../bin/win32/Debug/crowd.exe : 致命错误 LNK1120:4 未解决 外部
我的问题似乎是如何设置“allocToDevice”、“mapBuffer”、“setParameters”和“registerBuffer”方法,因为如果我注释掉这些方法,我就可以毫无问题地构建项目。
我在以下文件中定义了方法:
crowdSim.cuh:
extern "C"
{
void checkCUDAError(const char *msg);
void setParameters(SimParams *hostParams);
void registerBuffer(uint vbo);
void allocToDevice(void **ptr, int memSize);
void mapBuffer(void **ptr, uint vbo);
}
crowdSim.cu:
#include <cstdlib.h>
#include <cstdio.h>
#include <string.h>
#include <cuda_gl_interop.h>
// includes, kernels
#include "crowd_kernel.cu"
extern "C"
{
void checkCUDAError(const char *msg)
{
cudaError_t err = cudaGetLastError();
if( cudaSuccess != err)
{
fprintf(stderr, "Cuda error: %s: %s.\n", msg, cudaGetErrorString( err) );
exit(-1);
}
}
void setParameters(SimParams *hostParams)
{
// copy parameters to constant memory
cudaMemcpyToSymbol(params, hostParams, sizeof(SimParams));
}
void registerBuffer(uint vbo)
{
cudaGLRegisterBufferObject(vbo);
}
void allocToDevice(void **ptr, size_t memSize)
{
cudaMalloc(ptr, memSize);
}
void mapBuffer(void **ptr, uint vbo)
{
cudaGLMapBufferObject(ptr, vbo);
}
} //extern "C"
并且它们仅从crowdSim.cpp 中的“Crowd”类中的 _create 方法调用:
#include <math.h>
#include <memory.h>
#include <cstdio>
#include <cstdlib>
#include <GL/glew.h>
#include "crowdSim.h"
#include "crowdSim.cuh"
#include "crowd_kernel.cuh"
Crowd::Crowd(uint crowdSize) :
//numP(crowdSize),
hPos(0),
hVel(0),
dPosIn(0),
dVelIn(0),
dPosOut(0),
dVelOut(0)
{
params.numBodies = crowdSize;
_create(crowdSize);
}
Crowd::~Crowd()
{
//_remove();
crowdSize = 0;
}
uint
Crowd::newVBO(uint size)
{
GLuint vbo;
// glGenBuffers(1, &vbo);
// glBindBuffer(GL_ARRAY_BUFFER, vbo);
// glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
// glBindBuffer(GL_ARRAY_BUFFER, 0);
return vbo;
}
void
Crowd::_create(int numPeople)
{
crowdSize = numPeople;
unsigned int memSize = sizeof(float) * crowdSize * 4;
hPos = new float[crowdSize*4];
hVel = new float[crowdSize*4];
hPos = (float*) malloc(memSize);
hVel = (float*) malloc(memSize);
posVbo = newVBO(memSize);
registerBuffer(posVbo);
allocToDevice((void**) &dPosIn, memSize);
allocToDevice((void**) &dPosOut, memSize);
allocToDevice((void**) &dVelIn, memSize);
allocToDevice((void**) &dVelOut, memSize);
mapBuffer((void**)&dPosVbo, posVbo);
setParameters(¶ms);
}
我觉得我在这里遗漏了一些非常基本的东西,但我不知道是什么,所以任何帮助都会很棒!
您是否添加了 cuda.rules 文件以使 Visual Studio 能够识别 .cu 扩展名? cuda.rules 教 VS 如何处理 .cu,以便编译和链接它。有关设置的更多信息,请参阅这篇文章。
顺便说一句,如果头文件中函数的声明(原型)中有
extern "C"
,那么定义(实现)中不应该需要它。它可能会让你的代码更整洁 - 一般来说我根本不使用 extern "C"
。
我最近在从 C++ 代码调用 CUDA 函数时遇到了问题。我决定使用 extern 并遵循了一些在线教程。
读完你的代码后,我做了一件事不同的事情。我没有包含 cuda 文件 (crowdsim.cuh),而是在 C++ 代码中转发声明了该函数。我重写了 C++ 文件中的 extern 声明,并编译了代码,这次成功了。
这是我参考的教程。希望有帮助
http://codereflect.com/2008/09/29/how-to-call-cuda-programs-from-a-cc-application/
当然,只有当您没有混合的 c/c++ 和 Cuda 文件时,这种情况才是正确的,在这种情况下,NVCC 可以生成一些用于常规链接的对象以及 GPU 汇编对象语言中的一些代码。