在 C# 程序中使用多个用 C 编写的 DLL

Using multiple DLL's written in C within a C# program

我有一个用 C# 编写的程序。我想在这个程序中使用用 C 编写的 DLL。

public class Test
{
    [DllImport(@"C:/.../surcouche2.dll")]
    public static extern int refreshEntities();
}

我将函数称为:

Test.refreshEntities();

我正在使用 Visual Studio。为了创建 DLL surcouche2.dll,我创建了一个新的 Visual C++ 应用程序控制台,然后我选择了 DLL 并将选项保留为默认值。然后,我告诉VS用C编译。

函数是:

__declspec(dllexport) int refreshEntities() {
    int ret = 0;
    LibData *n;

    n = newLibData(LIB_MODULES_MODULE_ENTITES, LIB_MODULES_ACTION_SELECT,
            "http://10.0.2.2:4242/WebService1.asmx");
    if (n)
    {
        ret = n->refreshDb(n);
        n->destroy(n);
    }
    return (ret);
}

调用的函数在另一个DLL(被引用)中。但是我得到这个错误:

system.DllNotFoundException: Impossible de charger la DLL 'C:/.../surcouche2.dll': Le module spécifié est introuvable. (Exception de HRESULT : 0x8007007E)
   à app.Lol.refreshEntities()
   à app.MainWindow..ctor() dans c:\...\MainWindow.xaml.cs:ligne 30

但是,如果我像这样更改函数 refreshEntities,那么它就可以正常工作:

__declspec(dllexport) int refreshEntities() {
    return (42);
}

第二个 DLL 使用另一个 DLL(均在 C 中)。我使用选项 "create an empty project" 创建它们,所以我没有 stdafx.h, ... 文件。我想这不是问题,因为我可以在第二个 DLL 中使用第三个 DLL 中的函数。

如果无法解析加载的 dll 的依赖项,则会发生此错误。 首先,我建议您将两个本机程序集放在一个 bin 文件夹中并更改一个引用
[DllImport(@"C:/.../surcouche2.dll")][DllImport("surcouche2.dll")]

一般来说,Dependency Walker and Process Monitor 之类的工具对于调试依赖性问题很有用。首先有助于了解依赖项是什么,其次检查您的应用程序是否正在尝试查找组件。

配置 Process Monitor 以仅显示进程 activity 并使用您的应用程序名称应用进程名称过滤器,如下图所示,您将获得您的应用程序尝试访问的所有文件。它将有助于找到丢失的 dll。

[DllImport(@"C:/.../surcouche2.dll")]

这是坏主意,您还可以预览用户计算机上将出现的问题。像这样硬编码 DLL 的路径有助于 pinvoke 编组器在磁盘上找到 DLL 文件。但它绝对不能帮助操作系统找到 surchouce2.dll 需要的 DLL。就像包含 newLibData() 函数的那个​​一样。

错误信息经常被误解。它说 "cannot load" surcouche2.dll。这是准确的,但大多数程序员会将消息读为 "cannot find" surcouche2.dll。异常的最常见原因。不是这里的问题。

永远不要搞乱 DLL 地狱。将 DLL 保存在单独的目录中并在不同程序之间共享它们很有用的日子已经一去不复返了。始终将依赖的 DLL 复制到与需要它们的 EXE 相同的目录中。使得在操作系统上很容易找到它们。并避免您在找到错误文件时必须处理的大量痛苦。

使用项目 + 添加现有项和 select DLL。将他们的 Copy Local 属性 设置为 True。如果您不喜欢混乱,请在 post-build 事件中使用 XCOPY。