在 C# WPF 应用程序中使用外部C++ DLL
本文关键字:外部 C++ DLL WPF 应用程序 | 更新日期: 2023-09-27 18:35:14
完全披露...我是 C/C++/C# 新手。我一直在我的 linux 盒子 (http://ssdeep.sourceforge.net/) 上玩 ssdeep。
Python 包装器工作得很好(https://python-ssdeep.readthedocs.org/en/latest/usage.html)。我现在正在尝试编写使用此库的 Windows GUI 应用程序 (C# WPF)。在Windows二进制下载中,有许多文件,包括DLL和DEF文件。
在 API.TXT 文件中,作者写道:
Windows ssdeep 包包括一个 Win32 DLL 和一个 .def 文件。 尽管 MSVC 用户不能直接使用 DLL,但他们可以轻松创建 使用 Microsoft LIB 工具的 .lib 文件:
C:>lib/machine:i386/def:fuzzy.def
然后,您可以使用生成的库编译程序:
C:>cl sample.c fuzzy.lib
我已经这样做了,我现在有fuzzy.dll
、fuzzy.def
、fuzzy.exp
和fuzzy.lib
。经过多次谷歌搜索,我不确定如何在我的 WPF 应用程序中实际使用这些文件。
我应该把它放在解决方案中的什么位置(无论我需要什么文件)?我需要使用using System.Runtime.InteropServices;
吗?最好是,我会在我的代码中打包这个 dll 或 lib,这样它就不是外部依赖项,但在这一点上,我很乐意在库中调用一个函数。
编辑:
我找到了这个旧链接,它给了我这个代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
namespace FuzzyBear
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
[DllImport("fuzzy.dll")]
public static extern int fuzzy_hash_filename([MarshalAs(UnmanagedType.LPStr)] string fname, [MarshalAs(UnmanagedType.LPStr)] string result);
[DllImport("fuzzy.dll")]
public static extern int fuzzy_compare(string sig1, string sig2);
public MainWindow()
{
string result = "";
int test = fuzzy_hash_filename("C:''dev''tools''ssdeep-2.13''API.txt", result);
System.Diagnostics.Debug.Write("Lookie here: ");
System.Diagnostics.Debug.WriteLine(test.ToString());
InitializeComponent();
}
}
}
这给了我这个错误:
Additional information: A call to PInvoke function 'FuzzyBear!FuzzyBear.MainWindow::fuzzy_hash_filename' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
签名不匹配是什么意思?这是否意味着我的函数的输入与头文件的输入不匹配?这些是 cpp 头文件中的函数:
int fuzzy_hash_filename (const char *filename, char *result)
int fuzzy_compare (const char *sig1, const char *sig2)
不能像使用 C++ 那样链接到 C# 中的静态库,因此无法将代码打包在一起。 为了使用您的库,您将需要一个 Win32 DLL - 如果您只有一个 .lib,则需要为其创建一个包装器 DLL。
如果你有一个有效的 Win32 DLL,则可以使用 P/Invoke 从 C# 调用C++ DLL 上的方法。
为此,您需要声明要使用 DllImport 使用的每个C++方法。 我无法帮助您提供确切的语法,因为它取决于您要从 DLL 中使用的方法。 这方面的一个例子是:
DllImport("gdi32.dll", ExactSpelling=true, SetLastError=true)]static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
在 [http://www.pinvoke.net] 有一个标准 Win32 DLL 的 DllImport 声明库,它应该有助于你入门。
声明后,可以像在 .Net 中一样调用方法。 问题在于如何处理不同的数据类型 - 您需要了解如何使用 IntPtr。
你有一个 DLL。您需要使用 PInvoke 来调用 it 中的方法。
我强烈建议你得到亚当·内森(Adam Nathan)的优秀书,其中详细介绍了pinvoke http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X
教程中的 Pinvoke 很简单,但在现实生活中可能会变得复杂。这取决于方法签名