7

I have a simple function like this:

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 other 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 fine, 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 won't allow extern "C" __declspec (dllexport) with template functions is there any way to do this easily?actually I'm not expert,so would you please explain this to me in detail?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Alexander1991
  • 217
  • 5
  • 13

2 Answers2

8

There is no such thing as a "template function." There is a function template, however; that is a template from which functions are created by instantiation. In this case, the distinction is important.

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


If, on the other hand, you know all the types you would want to instantiate the template with when building your library, you can actually explicitly instantiate the template for those types and export these explicit instantiations. Like this:

Header file

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

Source 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 instantiations cannot be extern "C", however (they all have the same function name, after all). So if you want to load them dynamically, you'll have to provide uniquely-named C-linkage accessors to them.

Still, I believe what you're really looking for is implementing the funciton in a header file.


Based on your comments, here is how you could actually make your library dynamically loadable while using CUSP internally.

You cannot have a function template in your library's public interface. So let's say you want to allow using your library with the following types of LinearOperator: OperatorCharm and OperatorTop, and with the following types of Vector: FancyVector<float> and FancyVector<double>. Then, your public interface could 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 have to instantiate the template explicitly any more, since it will be instantiated implicitly for the calls in the EXPORT-ed functions.

So in effect, your public API will be those 4 cuspDsolver_a_b functions, which can be queried dynamically as normal.

Community
  • 1
  • 1
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • thank you so much for your answer however my function uses **CUSP** library and it has to compiled with **nvcc** but my other project is **VC++** I suppose I cannot include it, would you explain the second way a little bit more or reference me to a link that helps me to understand what your purpose is? – Alexander1991 Feb 25 '14 at 08:52
  • @user3297741 I don't really see why you couldn't link CUSP into a VS project. The CUDA SDK contains VS integration for CUDA files, after all. What exactly is the problem? – Angew is no longer proud of SO Feb 25 '14 at 08:54
  • actually I don't know either but here [Using cusp in a Visual Studio C++ project](http://stackoverflow.com/questions/21942540/using-cusp-in-a-visual-studio-c-project) says so. – Alexander1991 Feb 25 '14 at 08:59
  • @user3297741 OK, I wasn't aware CUSP was template-only. I've expanded the answer. – Angew is no longer proud of SO Feb 25 '14 at 09:05
  • Dear @Angew Thank you so much, I'm confused with your notation would you give me an example(I don'n know what do you mean by:`(params_which, correspond_to, OperatorCharm_and, FancyVector_of_float)` and `(params)`? – Alexander1991 Feb 25 '14 at 09:48
  • @user3297741 Here is a [mock example](http://ideone.com/pVQPxi). I hope it's clearer now. I don't know how the parameters `r`, `c`, `v` etc. in your original post correspond to `A`, `X`, `B` etc., so I couldn't write a more precise example. – Angew is no longer proud of SO Feb 25 '14 at 09:49
  • I guess you miss understood my code **LinearOperator** is not an example it is a class I mean it is not ***plus*** or ***minus*** it is a class it self which declared in a header file of ***CUSP***. – Alexander1991 Feb 25 '14 at 10:05
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/48352/discussion-between-angew-and-user3297741) – Angew is no longer proud of SO Feb 25 '14 at 10:09
1

Template functions are not compiled and thus not part of a DLL as there's an infinite number of function derived from a template.

Only specific instances of the template are compiled and linked into a binary. You can expose those specialized template functions in a DLL. You'll need a header file for those names as string them in a hardcoded string is problematic.

If you want to use a template function w/o specializing it, export it through a header file.

egur
  • 7,830
  • 2
  • 27
  • 47
  • thanks but there is another problem a cannot include header files, because it's from cusp library and have to compiled with **nvcc** but my project is **VC++**, is there any other way to do this? can I illustrate **typename LinearOperator** to compiler any other way than template? – Alexander1991 Feb 25 '14 at 08:38