构建 .NET 包装器是否需要源代码?
Is source code required to build a .NET wrapper?
是否需要 C++ 源代码来构建 .NET 包装器或静态库 *.lib
文件就足够了?
我们计划使用 SWIG。
谢谢。
w.r.t。你的问题专门询问静态库 *.lib
:
Is C++ source code required to build a .NET wrapper or static libraries *.lib files are just enough?
我怀疑您是否真的打算包装静态库:静态链接库通常不可再分发或可移植(例如,闭源静态库的作者需要在每次出现新的受支持的编译器时构建它们,例如,您不能将 GCC 库与 VisualC++ 2017 一起使用,并且 x64 VisualC++ 2017 库将与 x86 VisualC++ 2015 项目不兼容) - 即使您将 *.lib
加载到进程的内存中,并且跳转到 lib 映像内的已知函数地址,它会立即中断,因为静态库的代码将引用某些内存地址(例如字符串常量)which aren't yet relocated - 你会得到一个段错误(或 "Access violation" on Windows) 如果你 幸运 会崩溃(否则,它肯定会在被发现之前破坏你的进程的内存 space)。
P/Invoke in .NET Framework 和 .NET on Windows(即使用 [DllImport]
)仅支持 DLL(动态链接库),不支持静态链接库。
如果本机代码作为 COM 对象可用,或者可以通过 OLE、WMIC、ADSI 等平台功能访问(假设您的代码的进程与本机的 ISA 相同),您也可以调用本机代码您要调用的代码,因为它仍将加载到您的进程中,这就是为什么您不能使用 64 位 Office Excel 打开只有 32 位 OLE-DB 或 ODBC 驱动程序可用的数据库的原因).
当一个库作为 *.lib
可用时,您需要首先创建自己的本地主机 - 一个简单的 C/C++ Win32 (PE) EXE 或 DLL,它可以重新导出所有*.lib
中的有用函数就足够了 - 因为这些导出可以通过 C#/.NET 导入。
但总的来说:
- 如果要将 COM 对象导出到 .NET,则不需要源代码文件(
*.c
、*.cpp
)或头文件(*.h
和 *.hpp
),只有编译器会为你生成的 IDL 文件或 *.tlb
(Type-lib)。
- 如果您的本机代码也可通过其他平台功能使用,例如 OLE、ActiveX、COM 自动化 (
IDispatch
)、ODBC、OLE-DB、ADSI、WMI 等,那么您就不会使用 [ DllImport],这些平台都提供标准接口(如 ODBC 和 OLE-DB)
- 但一般来说,不需要 - 您不需要源代码(即
*.c
和 *.h
文件)来围绕从本机 DLL 导出的本机代码创建 .NET 包装器,并且使用 [DllImport]
导入到 .NET 中。
- 但是除了了解编译器设置(用于找出诸如调用约定、参数编组信息等)和 PE 检查器(以验证导出的函数至少存在于您要加载的 DLL 中)。
- 如果您正在为
AnyCPU
编译 C#/.NET 代码,请不要忘记确保为所有功能提供 x86 和 x64 本机 DLL(提示:Using a 32bit or 64bit dll in C# DllImport)
是否需要 C++ 源代码来构建 .NET 包装器或静态库 *.lib
文件就足够了?
我们计划使用 SWIG。
谢谢。
w.r.t。你的问题专门询问静态库 *.lib
:
Is C++ source code required to build a .NET wrapper or static libraries *.lib files are just enough?
我怀疑您是否真的打算包装静态库:静态链接库通常不可再分发或可移植(例如,闭源静态库的作者需要在每次出现新的受支持的编译器时构建它们,例如,您不能将 GCC 库与 VisualC++ 2017 一起使用,并且 x64 VisualC++ 2017 库将与 x86 VisualC++ 2015 项目不兼容) - 即使您将 *.lib
加载到进程的内存中,并且跳转到 lib 映像内的已知函数地址,它会立即中断,因为静态库的代码将引用某些内存地址(例如字符串常量)which aren't yet relocated - 你会得到一个段错误(或 "Access violation" on Windows) 如果你 幸运 会崩溃(否则,它肯定会在被发现之前破坏你的进程的内存 space)。
P/Invoke in .NET Framework 和 .NET on Windows(即使用 [DllImport]
)仅支持 DLL(动态链接库),不支持静态链接库。
如果本机代码作为 COM 对象可用,或者可以通过 OLE、WMIC、ADSI 等平台功能访问(假设您的代码的进程与本机的 ISA 相同),您也可以调用本机代码您要调用的代码,因为它仍将加载到您的进程中,这就是为什么您不能使用 64 位 Office Excel 打开只有 32 位 OLE-DB 或 ODBC 驱动程序可用的数据库的原因).
当一个库作为 *.lib
可用时,您需要首先创建自己的本地主机 - 一个简单的 C/C++ Win32 (PE) EXE 或 DLL,它可以重新导出所有*.lib
中的有用函数就足够了 - 因为这些导出可以通过 C#/.NET 导入。
但总的来说:
- 如果要将 COM 对象导出到 .NET,则不需要源代码文件(
*.c
、*.cpp
)或头文件(*.h
和*.hpp
),只有编译器会为你生成的 IDL 文件或*.tlb
(Type-lib)。 - 如果您的本机代码也可通过其他平台功能使用,例如 OLE、ActiveX、COM 自动化 (
IDispatch
)、ODBC、OLE-DB、ADSI、WMI 等,那么您就不会使用 [ DllImport],这些平台都提供标准接口(如 ODBC 和 OLE-DB) - 但一般来说,不需要 - 您不需要源代码(即
*.c
和*.h
文件)来围绕从本机 DLL 导出的本机代码创建 .NET 包装器,并且使用[DllImport]
导入到 .NET 中。- 但是除了了解编译器设置(用于找出诸如调用约定、参数编组信息等)和 PE 检查器(以验证导出的函数至少存在于您要加载的 DLL 中)。
- 如果您正在为
AnyCPU
编译 C#/.NET 代码,请不要忘记确保为所有功能提供 x86 和 x64 本机 DLL(提示:Using a 32bit or 64bit dll in C# DllImport)