在另一个项目中将模板函数用作dll



我有一个简单的函数,如下所示:

尖点.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)
{
.
.
.
.
.
}

我用这两行创建了一个dll:

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

我在其他项目中使用这种方法调用了这个函数:

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

这很好用,但现在我把我的功能改成了这个

//#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;
}

但是Visual Studio不允许extern"C"__declspec(dllexport)使用模板函数有什么方法可以轻松做到这一点吗?实际上我不是专家,请你详细解释一下好吗?

没有"模板函数"这回事。不过,有一个函数模板;这是一个通过实例化创建函数的模板。在这种情况下,区别很重要。

要调用从模板实例化的函数,您必须有权访问该实例化。最常见的情况是在头文件中实现模板,并简单地#include它(有关更多详细信息,请参阅此SO问题)。我相信您希望您的函数可以与客户端提供的任意类型(如LinearOperationVector)一起使用,因此仅头实现是您唯一的选择。


另一方面,如果您知道在构建库时要实例化模板的所有类型,则实际上可以显式实例化这些类型的模板,并导出这些显式实例化。像这样:

头文件

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

源文件

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.

然而,这样的实例化不能是extern "C"(毕竟它们都有相同的函数名)。因此,如果您想动态加载它们,就必须为它们提供唯一命名的C链接访问器。

尽管如此,我相信您真正想要的是在头文件中实现函数。


根据您的评论,以下是如何在内部使用CUSP的同时使库动态加载的方法。

库的公共接口中不能有函数模板。假设您希望允许将库与以下类型的LinearOperator一起使用:OperatorCharmOperatorTop,以及使用以下类型的VectorFancyVector<float>FancyVector<double>。然后,您的公共界面可能如下所示:

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

您甚至不必再显式实例化模板,因为它将为EXPORT-ed函数中的调用隐式实例化。

因此,实际上,您的公共API将是这4个cuspDsolver_a_b函数,它们可以像正常情况一样动态查询。

模板函数未编译,因此不是DLL的一部分,因为从模板派生的函数数量无穷多。

只有模板的特定实例才会被编译并链接到二进制文件中。您可以在DLL中公开那些专用的模板函数。您需要一个用于这些名称的头文件,因为在硬编码字符串中对它们进行字符串处理是有问题的。

如果你想使用一个没有专门化它的模板函数,可以通过一个头文件导出它。

最新更新