如何将 SWIG 生成的 C++ DLL 引用添加到 C# 项目?
How can I add a SWIG-generated C++ DLL reference to a C# project?
我正在使用 SWIG 生成一个 DLL,它将向 C# 项目公开 C++ 功能。目前我:
定义一个 SWIG 接口文件
%module example
%{
/* Includes the header in the wrapper code */
#include "../pointmatcher/PointMatcher.h"
%}
...
%include "../pointmatcher/PointMatcher.h"
使用 SWIG 生成 .cxx 包装器
swig.exe -c++ -csharp -outdir csharp example.i
通过 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] 加载=].
我正在使用 SWIG 生成一个 DLL,它将向 C# 项目公开 C++ 功能。目前我:
定义一个 SWIG 接口文件
%module example %{ /* Includes the header in the wrapper code */ #include "../pointmatcher/PointMatcher.h" %} ... %include "../pointmatcher/PointMatcher.h"
使用 SWIG 生成 .cxx 包装器
swig.exe -c++ -csharp -outdir csharp example.i
通过 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] 加载=].