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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With