如何将 SWIG 生成的 C++ DLL 引用添加到 C# 项目?

How can I add a SWIG-generated C++ DLL reference to a C# project?

我正在使用 SWIG 生成一个 DLL,它将向 C# 项目公开 C++ 功能。目前我:

  1. 定义一个 SWIG 接口文件

    %module example
    %{
    /* Includes the header in the wrapper code */
    #include "../pointmatcher/PointMatcher.h"
    %}
    
    ...
    
    %include "../pointmatcher/PointMatcher.h"
    
  2. 使用 SWIG 生成 .cxx 包装器

    swig.exe -c++ -csharp -outdir csharp example.i
    
  3. 通过 CMake 使用 MSBUILD 编译 .cxx 包装器

    # create wrapper DLL
    add_library(example SHARED ${WRAP_CSHARP_FILE})
    target_link_libraries(example pointmatcher)
    install(TARGETS example
            ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
            LIBRARY DESTINATION ${INSTALL_LIB_DIR}
            RUNTIME DESTINATION ${INSTALL_BIN_DIR})
    

然后我有一个 DLL 文件 (example.dll),我可以通过 Dependency Walker 检查它,并确认方法正在公开如下:

但是,当我尝试将此 MSVC DLL 添加为对 C# 项目的引用时,出现错误 "It is not a valid assembly or COM component"。

根据 How can I add a VC++ DLL as a reference in my C# Visual Studio project? 的回答,我已经确认 SWIG 本身会生成 P/Invoke 调用,并且 tlbimp 也无法识别 DLL。

您不会像添加 C# dll 那样将 C++ dll 添加到您的项目中。相反,它是通过 PInvoke 系统调用的。

SWIG 将为您生成一些 C# 代码,访问 dll 的最简单方法是将这些文件包含在您的项目中,这些文件通过您可以调用的一些 C# 函数公开 dll 功能。

你也可以自己通过PInvoke来使用dll。您需要创建一个将充当包装器的 C# 函数:

C++ Header:

#ifndef TESTLIB_H
#define TESTLIB_H

extern "C" {
    int myfunc(int a);
}

#endif

C++代码:

int myfunc(int a)
{
    return a+1;
}

C#代码:

using System;
using System.Runtime.InteropServices;

class Libtest
{
    [DllImport ("function")]
    private static extern int myfunc(int a);

    public static void Main()
    {
        int val = 1;
        Console.WriteLine(myfunc(val));
    }
}

输出:

2

DLL 的位置

编译后的 C++ dll 需要复制到 C# 项目的 bin 目录中,或者如果路径已知,可以将其添加到 DllImport 调用中:

[DllImport("path/to/dll/function.dll")]

要通过 swig 实现此目的,请使用 -dllimport 标志:

swig -cpp -csharp ... -dllimport "/path/to/dll/function.dll" ...

如果您想动态设置路径(以允许加载运行时动态选择的 32 位或 64 位版本),您可以使用 kernel32 函数 SetDllDirectory,它也使用 [=16] 加载=].