0

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

我试图调用这个方法: CreateGifFromEq("expression","path");

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

我没有在网上找到有关如何 MimeTex.dll在 C++ 中使用的资源。我只是在Pinvok的这个链接中找到了如何将它与 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);

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

4

3 回答 3

1

你肯定是想写:

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

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

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

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

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

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

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

于 2013-03-28T16:47:33.467 回答
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 并正常调用它们。

于 2013-03-28T16:49:14.400 回答
0

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

创建一个 C++/CLI 项目。它将成为 C# 和 C++ 之间的接口(这是 C++/CLI 的目标)。

使您的 C# 项目具有对这个新程序集的引用。

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

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

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

于 2013-03-28T16:55:28.510 回答