从dll调用本机方法

时间:2013-03-28 16:41:59

标签: c# .net visual-c++ dll c++-cli

我正在尝试在C ++ / CLI项目的混合模式中使用MimeTex.dll。我包括dll: #pragma comment(lib,"MimeTex.dll")

我尝试调用此方法: CreateGifFromEq("expression","path");

但编译器通知它不知道CreateGifFromEq()方法。

我没有在网上找到有关如何在C ++中使用MimeTex.dll的资源。我只是在Pinvok的this link中找到了如何将它与C#一起使用,如:

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

如果没有Pinvok在C ++ / CLI的混合模式下如何调用它?

3 个答案:

答案 0 :(得分:1)

当然你打算写:

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

换句话说,您将.lib文件传递给链接器而不是.dll。编译DLL时,将生成.lib文件。

但那不是你眼前的问题。编译器没有CreateGifFromEq的声明。那是因为你没有在你的C ++代码中包含库的头文件。这样做可以解决问题。

如果你需要的只是一个函数,那么在你的C ++代码中声明它应该是微不足道的。

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

您可能还需要将其包装在extern "C"块中。

实际上,在查看了库之后,源代码提供的头文件并没有声明该函数,即使它存在于库中。

答案 1 :(得分: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并正常调用它们。

答案 2 :(得分:0)

有一种更清洁的做事方式:

创建C ++ / CLI项目。它将是您在C#和C ++之间的接口(这是C ++ / CLI的目标)。

让你的C#项目引用这个新程序集。

在新的C ++ / CLI项目中,配置项目选项,以便指向包含mimetex .h文件的目录,以便编译器编译项目,以及链接的.lib / .dll目录。

在C ++ / CLI部分中,您只需在函数内部编写C ++。它们暴露在你的C#程序集中,但在内部它只是像往常一样调用C ++函数。 (您应该查看C ++ CLI教程,了解如何处理字符串以将它们转换为本机字符或std :: string。我记得我必须查看它。)*

在C#部分中,您只需调用C ++ CLI项目程序集公开的函数,例如普通的C#函数,而不会注意它的后面的本机代码。