Im trying to create a framework to be able to use CUDA code in several game engine. To be able to communicate with all the wanted engines the frame consists of two main parts. A Lib and a DLL. The Lib contains all the functionality (CUDA and regular C++) and the DLL functions as a bridge to call functions from the Lib.
Now, everything was running oke untill I've included a .cu file. When I'm building I'm getting the following error:
Error 3 error LNK2019: unresolved external symbol _Add2And7 referenced in function "public: void __thiscall PerceptorHost::UpdatePerceptorHost(void)" (?UpdatePerceptorHost@PerceptorHost@@QAEXXZ) D:\_Professional\DAE_Research\2_Projects\PWO_ePerceptor\Source\build\src\Native_ePerceptor_Dll\Native_ePerceptor_Lib.lib(PerceptorHost.obj) Native_ePerceptor_Dll
When I look at the buildlogs the Lib is building fine (Native_ePerceptor_Lib.lib). It's the DLL that fails.
Last but not least, the project has to be created using CMake (to be able to tackle different setups). Below you can find snippets of the .cu, Lib .cpp en the Dll .cpp. I looked across the interwebs to be able to find a solution but most of the solutions are regarding issues in one project and not regarding libraries. I'm pretty desperate at the moment so I hope some of you can point out what the issue, and hopefully, what a possible solution is. One more thing, I'm pretty sure all the necessary libraries are being included (cudart, cuda).
Kernel.cu
#include <cuda\cuda_runtime.h>
__global__ void add(int a, int b, int *c)
{
*c += a + b;
printf("%i + %i = %i \n", a, b, *c);
}
extern "C" void Add2And7(int *c)
{
int *dev_c;
//Allocate GPU memory
cudaMalloc((void**)&dev_c, sizeof(int));
add <<<1, 1>>>(2, 7, dev_c);
//Copy GPU to CPU
cudaMemcpy(c, dev_c, sizeof(int),
cudaMemcpyDeviceToHost);
//printf("number is %u \n", &c);
//Free allocated GPU memory
cudaFree(dev_c);
}
PerceptorHost.cpp
//Forward declaration
extern "C" void Add2And7(int *c);
void PerceptorHost::UpdatePerceptorHost()
{
if (!g_bIsBooted)
return;
if (!m_bTestKernel)
{
int output = 0;
Add2And7(&output);
printf("2 + 7 = %i \n", output);
m_bTestKernel = true;
}
}
DLL.cpp
extern "C" NATIVEDLL_API void __cdecl UpdatePerceptorHost()
{
PERCEPTORHOST->UpdatePerceptorHost(); //Update the PerceptorHost and all it's managers
}
CMAKE
########################################################################
# Add all source files to variables
# CPU Source Files
FILE(GLOB SRCS *.cpp)
FILE(GLOB HDRS *.h )
FILE(GLOB CUDA_HDRS
${CMAKE_SOURCE_DIR}/include/cuda/*.h)
FILE(GLOB CALIBRATION_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Calibration/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Calibration/*.h)
FILE(GLOB CORE_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Core/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Core/*.h)
FILE(GLOB DATAPROVIDER_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Data/DataProvider/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Data/DataProvider/*.h)
FILE(GLOB RESOURCEMANAGER_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Data/ResourceManager/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Data/ResourceManager/*.h)
FILE(GLOB DEBUG_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Debug/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Debug/*.h)
FILE(GLOB EXCEPTION_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Exceptions/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Exceptions/*.h)
FILE(GLOB HELPERS_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Helpers/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Helpers/*.h)
FILE(GLOB VIDEOWRITER_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/VideoWriter/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/VideoWriter/*.h)
# GPU Source Files
FILE(GLOB GPU_HELPERS_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Helpers/*.cuh
${CMAKE_CURRENT_SOURCE_DIR}/Helpers/*.cu)
########################################################################
# Group all source files
SOURCE_GROUP("Calibration" FILES ${CALIBRATION_FILES})
SOURCE_GROUP("Core" FILES ${CORE_FILES})
SOURCE_GROUP("DataProvider" FILES ${DATAPROVIDER_FILES})
SOURCE_GROUP("ResourceManager" FILES ${RESOURCEMANAGER_FILES})
SOURCE_GROUP("Debug" FILES ${DEBUG_FILES})
SOURCE_GROUP("Exceptions" FILES ${EXCEPTION_FILES})
SOURCE_GROUP("Helpers" FILES ${HELPERS_FILES})
SOURCE_GROUP("VideoWriter" FILES ${VIDEOWRITER_FILES})
########################################################################
# Set this part as static lib
IF (D_ENABLE_LIBRARY_CUDA)
CUDA_ADD_LIBRARY(Native_ePerceptor_Lib
${CUDA_HDRS}
${CALIBRATION_FILES}
${CORE_FILES}
${DATAPROVIDER_FILES}
${RESOURCEMANAGER_FILES}
${DEBUG_FILES}
${EXCEPTION_FILES}
${HELPERS_FILES}
${VIDEOWRITER_FILES}
${SRCS}
${HDRS}
${GPU_HELPERS_FILES}
)
ELSE()
ADD_LIBRARY(Native_ePerceptor_Lib
${CUDA_HDRS}
${CALIBRATION_FILES}
${CORE_FILES}
${DATAPROVIDER_FILES}
${RESOURCEMANAGER_FILES}
${DEBUG_FILES}
${EXCEPTION_FILES}
${HELPERS_FILES}
${VIDEOWRITER_FILES}
${SRCS}
${HDRS}
)
ENDIF()
########################################################################
# Add preprocessor defines
IF (D_ENABLE_LIBRARY_CUDA)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11 FATAL_ERROR)
FIND_PACKAGE(CUDA REQUIRED)
INCLUDE_DIRECTORIES(
${CUDA_INCLUDE_DIRS}
)
set(CUDA_ENABLED ON)
add_definitions(-DCUDA_ENABLED=1)
ENDIF (D_ENABLE_LIBRARY_CUDA)
IF (D_ENABLE_LIBRARY_OpenCV)
add_definitions(-DOPENCV_ENABLED=1)
ENDIF (D_ENABLE_LIBRARY_OpenCV)
IF (D_ENABLE_LIBRARY_Glut)
add_definitions(-DGLUT_ENABLED=1)
ENDIF (D_ENABLE_LIBRARY_Glut)
########################################################################
# Include Directories
TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
${CUDA_LIBRARIES})
TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
${OpenCV_LIBRARIES})
TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
${Tobii_LIBRARIES})
TARGET_LINK_LIBRARIES(Native_ePerceptor_Lib
${Glut_LIBRARIES})
Oke, I was able to resolve the issue without the previous mentioned solution (changing Build Customization + setting file to CUDA C/C++)
The problem was that indeed the symbols of my header file that defined my CUDA function was not being exported. So with my project structure (LIB -> DLL -> CMD) this was an issue. I was able to using it in a LIB -> CMD structure. I resolved the issue by defining the header function as follow:
instead of:
I don't know if there is anything wrong with doing this (it works :))? If I check out MSDN I think it fine using the export keyword.
Using _declspec(dllexport)