首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >从dll调用本机方法

从dll调用本机方法
EN

Stack Overflow用户
提问于 2013-03-28 16:41:59
回答 3查看 4.4K关注 0票数 0

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

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

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

我在网上找不到how to use MimeTex.dll in C++的资源。我只是发现如何在Pinvok的this link中使用它和C#,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[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);
}

然后这样叫它:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
NativeMethods.CreateGifFromEq(equation, tempGifFilePath);

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-03-28 16:47:33

你肯定是想写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma comment(lib,"MimeTex.lib")

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

但这不是你的当务之急。编译器没有针对CreateGifFromEq的声明。这是因为您的C++代码中没有包含该库的头文件。这样做应该可以解决问题。

如果只需要一个函数,那么在C++代码中声明它应该很简单。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
__declspec(dllimport) extern int CreateGifFromEq(char *expr, char *fileName);

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

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

票数 1
EN

Stack Overflow用户

发布于 2013-03-28 16:49:14

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

如果您不想使用P/Invoke,另一种方法是使用LoadLibrary加载DLL,并使用GetProcAddress获取指向函数的指针。

下面是C++/CLI中C#代码的等价物:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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++中是不必要的):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HMODULE hModule = LoadLibrary(L"MimeTex.dll");
int (*fpCreateGifFromEq)(WCHAR*, WCHAR*) = GetProcAddress(hModule, "CreateGifFromEq");
(*fpCreateGifFromEq)(L"expression", L"filename");

你不需要为GetModuleHandle和FreeLibrary做这件事,因为它们来自kernel32.dll,所以你可以只包含Windows.h并正常调用它们。

票数 1
EN

Stack Overflow用户

发布于 2013-03-28 16:55:29

有一种更干净的方式做事情:

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

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

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

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15687468

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文