2014-02-25 48 views
7

我有一個簡單的功能是這樣的:使用模板功能的DLL中的另一個項目

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

,我創建了使用這兩種線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)的模板函數有什麼辦法輕鬆做到這一點?其實我不是專家,所以你能詳細解釋一下嗎?

回答

5

沒有「模板功能」這樣的東西。有一個函數模板,然而,;這是通過實例化從中創建函數的模板。在這種情況下,區分很重要。

要調用從模板實例化的函數,您必須有權訪問該實例。最常見的情況是在頭文件中實現模板,並簡單地使用#include它(有關更多詳細信息,請參閱此SO question)。我相信您希望您的函數可以使用任意客戶端提供的類型,如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-linkage訪問器。

不過,我相信你真正需要的是在頭文件中實現功能。


根據你的意見,這裏是你如何實際使你的庫動態加載,而在內部使用CUSP。

在庫的公共接口中不能有函數模板。因此,假設您要允許使用以下類型的庫:LinearOperatorOperatorCharmOperatorTop,以及以下類型的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函數,它們可以像平常一樣動態查詢。

+0

非常感謝你的回答,但是我的函數使用** CUSP **庫,它必須用** nvcc **編譯,但是我的其他項目是** VC++ **我想我不能包含它,你能解釋一下嗎?第二種方式多一點,或者引用我的鏈接,幫助我理解你的目的是什麼? – Alexander1991

+0

@ user3297741我真的不明白爲什麼你無法將CUSP鏈接到VS項目中。畢竟,CUDA SDK包含用於CUDA文件的VS集成。究竟是什麼問題? – Angew

+0

其實我也不知道,但這裏[在Visual Studio C++項目中使用CUSP](http://stackoverflow.com/questions/21942540/using-cusp-in-a-visual-studio-c-project)說所以。 – Alexander1991

1

模板函數沒有被編譯,因此不是DLL的一部分,因爲從模板派生的函數有無數個。

只有模板的特定實例被編譯並鏈接到二進制文件中。您可以在DLL中公開這些專門的模板函數。您將需要這些名稱的頭文件,因爲它們在硬編碼字符串中是有問題的。

如果您想使用不專門化的模板函數,請通過頭文件導出它。

+0

謝謝,但還有一個問題不能包含頭文件,因爲它來自cusp庫,必須用** nvcc **編譯,但我的項目是** VC++ **,有沒有其他方法可以做到這一點?我可以說明** typename LinearOperator **以編譯任何其他方式比模板? – Alexander1991

相關問題