2013-03-28 56 views
0

我試圖在混合模式的C++/CLI項目中使用MimeTex.dll。包括我的DLL是: #pragma comment(lib,"MimeTex.dll")從dll調用本地方法

,我試圖調用此方法: CreateGifFromEq("expression","path");

但是編譯器告知它不知道CreateGifFromEq()方法。

我在網上找不到關於如何在C++中使用MimeTex.dll的資源。我只是找到了如何使用C#中this link通過Pinvok喜歡使用它:

[System.Security.SuppressUnmanagedCodeSecurity()] 
internal class NativeMethods 
{ 
    private NativeMethods() 
    { //all methods in this class would be static 
    } 

    [System.Runtime.InteropServices.DllImport("MimeTex.dll")] 
    internal static extern int CreateGifFromEq(string expr, string fileName); 

    [System.Runtime.InteropServices.DllImport("kernel32.dll")] 
    internal extern static IntPtr GetModuleHandle(string lpModuleName); 

    [System.Runtime.InteropServices.DllImport("kernel32.dll")] 
    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)] 
    internal extern static bool FreeLibrary(IntPtr hLibModule); 
} 

,然後調用它像:

NativeMethods.CreateGifFromEq(equation, tempGifFilePath); 

我怎麼能在C++/CLI的混合模式稱之爲無Pinvok?

回答

1

當然,你的意思是寫:

#pragma comment(lib,"MimeTex.lib") 

換句話說,你的.lib文件傳給連接器,而不是.dll文件。當您編譯該DLL時,將生成一個.lib文件。

但這不是你的直接問題。編譯器沒有CreateGifFromEq的聲明。這是因爲你沒有在你的C++代碼中包含庫的頭文件。這樣做應該可以解決問題。

如果您只需要一個函數,那麼在C++代碼中聲明它就應該是微不足道的。

__declspec(dllimport) extern int CreateGifFromEq(char *expr, char *fileName); 

你可能會需要包裝,在一個extern "C"塊了。

實際上,在查看過庫之後,與源一起提供的頭文件不會聲明該函數,即使它存在於庫中。

+0

它的作品很棒thx。 – Aan

+0

很高興聽到 –

1

在C++/CLI中,您可以像在C#中一樣使用P/Invoke。

如果您不想使用P/Invoke,另一種方法是使用LoadLibrary加載DLL並獲取指向GetProcAddress函數的指針。


下面是C++/CLI的C#代碼相當於:

using namespace System; 
using namespace System::Runtime::InteropServices; 

private ref class NativeMethods abstract sealed 
{ 
internal: 
    [DllImport("MimeTex.dll")] 
    static int CreateGifFromEq(String^ expr, String^ fileName); 

    [DllImport("kernel32.dll")] 
    static IntPtr GetModuleHandle(String^ lpModuleName); 

    [DllImport("kernel32.dll")] 
    [returnvalue: MarshalAs(UnmanagedType::Bool)] 
    static bool FreeLibrary(IntPtr hLibModule); 
}; 

正如你可以看到它的,除了一些小的語法變化幾乎相同的C#代碼。

這裏是你將如何使用調用LoadLibrary和GetProcAddress(其不需要封送處理,這在C不必要++反正的優勢):

HMODULE hModule = LoadLibrary(L"MimeTex.dll"); 
int (*fpCreateGifFromEq)(WCHAR*, WCHAR*) = GetProcAddress(hModule, "CreateGifFromEq"); 
(*fpCreateGifFromEq)(L"expression", L"filename"); 

你並不需要做的是對的GetModuleHandle和FreeLibrary則,因爲它們來自kernel32.dll,因此您可以只包含Windows.h並正常調用它們。

+0

C++/CLI中的Pinvok怎麼樣,可以將上面的C#代碼改寫成C++/CLI,我會很感激。 – Aan

+0

我以爲你不想使用p/invoke。從C++/CLI中毫無意義。你最好以你試圖這樣做的方式去做。讓它工作並不難。 –

+0

@DavidHeffernan:之前我不想使用Pinvok,但是因爲我嘗試了你的方式,但是我無法讓它與我合作。所以我回到了以前從未使用過的Pinvok。也感謝你的回答,但實際上我沒有'.lib'或'.h'文件,所有我擁有的是'MimTex.dll'。 – Aan

0

有做事情的更清潔的方式:

創建一個C++/CLI項目。它將成爲C#和C++之間的接口(這是C++/CLI的目標)。

讓你的C#項目有一個對這個新程序集的引用。

在您的新C++/CLI項目中,配置項目選項以便指向編譯器編譯項目的mimetex .h文件的目錄,以及鏈接器的.lib/.dll目錄。

在您的C++/CLI部分中,您只需在函數內部編寫C++。他們暴露於你的C#程序集,但在內部它只是像往常一樣調用C++函數。 (你應該檢查一個C++ CLI教程知道該怎麼做的字符串,將它們轉換爲本地字符或std ::字符串。我記得我有看那個。)*

在你的C#部分,您只需調用C++ CLI項目程序集公開的函數(如普通C#函數),而不會注意到它是本地代碼的後臺。