cuda obj files in a dll trying to create a dll using .cu files

Hi,

I am working on a project that requires creating a dll file which contains some cuda functions.

The problem is, .cu file does not get exported into the dll i.e. my application linked to the dll, cannot find functions declared in .cu files. I am getting LNK2019 unresolved external symbol error with VS2005.

In my project, I can define other functions in seperate cpp files and they are exported correctly - however .cu functions not.

Can anyone tell how can I export cuda files to the dll.

Thanks in advance,
Pinky

Are you declaring the functions ‘extern “C”’?

The function declaration in a .h file looks like this

extern “C” __declspec(dllexport) void __cdecl Init( void )

The function definition is in .cu file

extern “C” void Init()

This is just a device query function.

The code compiles fine and creates a dll too. But my application dependent on this

dll gives the LNK2019 error, and says Init is unreferenced.

Am I missing something?

I created a .lib file that works by wrappping a C++ class around the methods in the .CU file. I believe it should be the same for dll.

Simply create a regular class - in the .cpp file forward declare the method of the .cu file that you wish to call and create a method that calls that function. In the .cu file the method header should look like that:

extern "C" void myMethod()

The class methods can be called when compiled into the lib.

Hi Seb,

Could you give more details about how you did implement your library? I saw an implementation of a library pug by Mark Harris, but it is for cg code. I will appreciate your explanation. Thanks,

Diego

It’s rather simple:

Let’s say you have created your kernel called testKernel(). And you created a function testLauncher() that executes the kernel (with <<< >>> and cudaMemcpy and all those cool things). Both are C/CUDA functions. To execute your kernel you have to call testLauncher().

What you do now is declare your testLauncher() as extern “C”:

/* the old function declaration.. */

void testLauncher(int param1, int param2 ...)

{

  /*prepare and launch kernel here*/

}

/* is rewritten to look like that: */

extern "C" void testLauncher(int param1, int param2 ...)

{

  /*prepare and launch kernel here*/

}

Now create a class that has a method callTestLauncher(). In the file where callTestLauncher() is implemented the testLauncher() function has to be forward declared so in on of the first lines of the class cpp file put

extern "C" void testLauncher(int param1, int param2 ...);

Now in the callTestLauncher() method you can call the testLauncher function:

testLauncher(256, 25, ...);

which when executed will launch the kernel. So you’re call graph would be something like: callTestLauncher()->testLauncher()->testKernel() whereas the first method can be a regular c++ class method.

When this is compiled as a .lib file the kernel can be launched by calling callTestLauncher().

Thanks a lot :). This method worked!

This method works indeed; however, it seems that wrapping all CUDA calls in C functions would make the use of C++ classes pretty cumbersome. If most of the methods in a C++ class implement CUDA functionality then the class would basically be reduced to a data container, and if that’s the case I’d rather use regular C struct’s. I wonder if NVIDIA has any plans to support full blown C++ accessible CUDA.

I have an application using GPU and OpenGL. I compiled the project to obtain a dll file and I wanna use that dll to call the application as a thread of C# GUI project. I declared the export of the dll project as:

extern “C” __declspec(dllexport) void CUDA_main( void );

If i don’t include the cuda kernel (.cu files), it works fine with openGL in C# (no nvcc objects). However, when .cu files are added to the dll, the dll does not work in the C#. Such that the C# code throws “System.DLLnotFoundException” error.

I wanna ask how to obtain a working dll from the cuda projects.

My build flags for .cu files:

(CUDA_BIN_PATH)\nvcc.exe -ccbin "(VCInstallDir)bin" -c -DWIN32 -D_CONSOLE -D_MBCS -Xcompiler /EHsc,/W3,/nologo,/Wp64,/O2,/Zi,/MT -I"(CUDA_INC_PATH)" -I./ -I../../common/inc -o (ConfigurationName)\template.obj template.cu

Are there any missing project setting or compiler flags?

I’ve the same problem, tried to add the -shared flag, but it doesn’t work.

I think, maybe, NVidia should give a cpp template for dll project in their SDK.

I have solved the problem :whistling: :

As far as I understand, if the dll contains the obj files that created by nvcc, C# side does not recognize this dll. So I splitted my dll project into two projects:

i) Cuda_Kernel

ii) Cuda_API

First one is including the kernel files and does the real job and the other is to call the first dll.

Cuda_Kernel project has one entry function and defined as:

“extern “C” __declspec( dllexport ) void runTest(Parameters *params)”.

This project outputs “cuda_Kernel.dll”

Cuda_API project also has one entry function and defined as:

“extern “C” __declspec( dllexport ) int CUDA_main(Parameters *params”.

Here is the code of CUDA_main function:

extern "C" __declspec( dllexport ) int CUDA_main(Parameters *params)

{

	// get handle to dll 

	HINSTANCE hGetProcIDDLL = LoadLibrary("cuda_Kernel.dll");

	// get pointer to the function in the dll

	FARPROC lpfnGetProcessID = GetProcAddress(HMODULE(hGetProcIDDLL), "runTest");

	//Define the Function in the DLL for reuse. This is just prototyping

	//the dll's function. A mock of it. Use "stdcall" for maximum

	//compatibility.

	typedef void (* pICFUNC)(Parameters*);

	pICFUNC runTest;

	runTest = pICFUNC(lpfnGetProcessID);

	// The actual call to the function contained in the dll 

	runTest(params);

	// Release the Dll 

	FreeLibrary(hGetProcIDDLL);

	return 0;

}

This project outputs “cuda_API.dll”.

And from C# side “CUDA_main” is called like this:

class CUDAMAIN_class

    {

        [DllImport("cuda_API.dll")]

        public static extern int CUDA_main(ref Parameters p);

       public void CUDA_main_call(ref Parameters p)

        {

            CUDA_main(ref p);

        }

   }

  ...

   

   CUDAMAIN_class my_cuda = new CUDAMAIN_class();

   my_cuda.CUDA_main_call(ref params_struct);

I hope this helps :thumbup:

[Solution] I too struggled with this problem. The simplest solution that I have found for generating a dll with cuda functionality and importing into C# is as follows:

(Tested on Cuda v1.0. I hear there are problems in 0.8)

  1. Declare exports in cu file (or header file). Example:
extern "C" __declspec(dllexport) char* GetCudaDeviceName(int);
  1. Compile with the -shared flag. Use the -o flag to name the dll. Without this flag your dll will be named a.exe. I didnt realize that this was actually a dll until i tried to execute it. Example:
nvcc -ccbin "C:\Program Files\Microsoft Visual Studio 8\VC\bin" test.cu -shared -o test.dll

3)Declare an external function in C#. (I chose to place the dll in the project \debug folder with the managed executable). Note: The return:MarshalAs() attribute is specific to my example and instructs the CLR to convert the char* to a managed string.

[DllImport("test.dll")]

[return:MarshalAs(UnmanagedType.AnsiBStr)]

extern static string GetCudaDeviceName(int deviceId);

4)Invoke function.

...

String name=GetCudaDeviceName(0));

...

I hope this saves someone a headache.

I’m trying to build a static library with nvcc. It will have some functions which I would like to call from a C++ class. Library seems to build ok, but when I link it with my C++ project I keep getting “undefined reference to”. Could you explain me what I’m doing wrong?

I’m using Netbeans on Ubuntu. I compiled and run other CUDA application so I’m pretty sure it’s not CUDA configuration issue.

First project cudaPSO has two files: cudaswarm.h ( http://www.nopaste.pl/i6j ) and cudaswarm.cu ( http://www.nopaste.pl/i6k ).

Here’s make output: http://www.nopaste.pl/i6l

First project is compiled with nvcc, second with g++ 4.3.4. Netbeans handles all makefiles. Please give me a clue, because I’m out of them.

Shouldn’t the .h file (used by everyone but the DLL code) say:

extern “C” __declspec(dllimport) void __cdecl Init( void )

The DLL would use:

extern “C” __declspec(dllexport) void __cdecl Init( void )

How did you get dll from .cu project in the first place? I couldn’t even do that. In mS2017 I can only get exe file.