Using a template function as a dll in another project

I have a simple function:

cusp.dll

#define EXPORT extern "C" __declspec (dllexport) EXPORT void cuspDsolver(int *r, int *c, double *v, double *x, double *b, int size, int nnz,double tol) { . . . . . } 

and I created a dll using these two lines:

 #define EXPORT extern "C" __declspec (dllexport) EXPORT 

and I called this function in another project using this method:

 HINSTANCE hDLL = LoadLibrary("C:\\Users\\Administrator\\Documents\\Visual Studio 2012\\Projects\\Ardalan_12\\cusp.dll"); if(hDLL == NULL) { cout<< "Failed to load DLL" <<endl; } typedef void(*fnPtr)(int *, int *, double *, double *, double *, int , int ,double); fnPtr pfn; pfn=(fnPtr)GetProcAddress(hDLL,"cuspDsolver"); if(pfn) { pfn(rowOffset,colIndex,values,answer,rightHandSide,theSize,nnz,0.9); } FreeLibrary(hDLL); 

this works very well, but now I changed my function to this

 //#define EXPORT extern "C" __declspec (dllexport) //EXPORT template <typename LinearOperator,typename Vector> void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol) { cusp::default_monitor<double> monitor(B, 10000, tol); cusp::precond::scaled_bridson_ainv<double,cusp::device_memory> PRE(A); DWORD dw1 = GetTickCount(); cusp::krylov::cg(A,X,B,monitor,PRE); DWORD dw2 = GetTickCount(); double dw3 = dw2 - dw1; cout <<endl << "time spent is : " << dw3 << endl; cout << endl << "developed by cusp!!!" << endl; } 

but Visual Studio will not allow extern "C" __declspec (dllexport) with template functions . Is there any way to make this easy? I'm not really an expert, so please explain this to me in detail?

+7
c ++ dll
source share
2 answers

There is no such thing as a “template function”. However, there is a function template; This is the template from which functions are created by instantiating. In this case, distinction is important.

To call a function created from a template, you must have access to this instance. The most common case is to implement a template in the header file and just #include it (see this SO question for more details). I believe that you want your function to be usable with arbitrary client types like LinearOperation and Vector , so the only option is for headers only.


If, on the other hand, you know all the types that you want to instantiate the template when creating the library, you can explicitly create an instance of the template for these types and export these explicit instances. Like this:

Header file

 template <typename LinearOperator,typename Vector> void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol); 

Original file

 template <typename LinearOperator,typename Vector> void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol) { // body here } template __declspec(dllexport) void cuspDsolver(MyConcreteOperator1& A, MyConcreteVector1& X, MyConcreteVector1& B, double tol); template __declspec(dllexport) void cuspDsolver(MyConcreteOperator2& A, MyConcreteVector2& X, MyConcreteVector2& B, double tol); // etc. 

Such instances cannot be extern "C" , however (they all have the same function name, after all). Therefore, if you want to dynamically load them, you will have to give them access to them with unique names.

However, I believe that you are really looking for implementing funciton in the header file.


Based on your comments, here's how you could make your library dynamically load when using CUSP internally.

You cannot have a function template in the public library interface. Therefore, suppose you want to allow your library to be used with the following LinearOperator types: OperatorCharm and OperatorTop and with the following Vector types: FancyVector<float> and FancyVector<double> . Then your open interface might look like this:

 template <typename LinearOperator,typename Vector> void cuspDsolver(LinearOperator& A,Vector& X,Vector& B,double tol) { // body } EXPORT void cuspDsolver_Charm_float(params_which, correspond_to, OperatorCharm_and, FancyVector_of_float) { cuspDsolver(params); } EXPORT void cuspDsolver_Charm_double(params_which, correspond_to, OperatorCharm_and, FancyVector_of_double) { cuspDsolver(params); } EXPORT void cuspDsolver_Top_float(params_which, correspond_to, OperatorTop_and, FancyVector_of_float) { cuspDsolver(params); } EXPORT void cuspDsolver_Charm_double(params_which, correspond_to, OperatorTop_and, FancyVector_of_double) { cuspDsolver(params); } 

You don’t even need to explicitly create an instance of the template, since it will be implicitly created for calls in EXPORT -ed functions.

Thus, your public API will be those 4 cuspDsolver_a_b functions that can be requested dynamically as usual.

+5
source share

The functions of the template are not compiled and therefore are not part of the DLL, since there are an infinite number of functions obtained from the template.

Only specific instances of the template are compiled and linked in binary format. You can open these specialized template functions in a DLL. You will need a header file for these names, since a hard-coded string is problematic.

If you want to use the template function without specialization, export it through the header file.

+1
source share

All Articles