CUDA Link Error (Lib to Dll)

2019-08-09 17:24发布

问题:

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

回答1:

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:

extern "C" __declspec(dllexport) void Add2And7(int *); 

instead of:

extern "C" void Add2And7(int *);

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)

The dllexport and dllimport storage-class attributes are Microsoft-specific extensions to the C and C++ languages. You can use them to export and import functions, data, and objects to or from a DLL.



标签: c++ c dll cuda