编译可供C#调用的C/C++动态链接库dll文件

编译可供C#调用的C/C++动态链接库dll文件,C语言控制台应用程序,探索生成dll过程

由于项目需求,需要公司另一个团队提供相关算法支持,是用C语言编译好的dll库提供给我们进行调用。

但是拿到dll文件,以及算法实现函数声明文档后,出现了各种问题。

是按照这篇博客 http://blog.csdn.net/caowei880123/article/details/6387839 进行操作的。

1.无法加载dll,应用程序并行配置不正确的错误

An unhandled exception of type 'System.DllNotFoundException' occurred in Aes.exe

Additional information: 无法加载 DLL“a.dll”: 应用程序无法启动,因为应用程序的并行配置不正确。有关详细信息,请参阅应用程序事件日志,或使用命令行 sxstrace.exe 工具。 (异常来自 HRESULT:0x800736B1)。

折腾了一天都无法解决,只有联系他们,拿到源码自己编译一遍。

2.编译过程中也是各种问题。拿到源码,发现并没有通过 __declspec(dllexport) 来声明函数,从而对外暴露,而且是一个控制台应用程序

曾尝试创建新的dll工程,添加相应的.h和.c文件,来进行编译。编译过程中,必须将.c文件后缀修改为cpp文件。然后又

出现了许多类型转换错误。无奈,时间有限,不敢修改原代码,也不敢用C#重新实现一边。只有通过原来的控制台应用程序生成dll文件。

3.C语言控制台应用程序,探索生成dll过程

先将Debug 修改为 Release 模式,因为debug模式下生成的dll文件可能会出现问题。

选择项目(Project)->属性(Properties)-> General -> Configuration Type,修改为 Dynamic Library (.dll)

点击rebuild重新生成,不要按F5运行。发现Release 文件夹下并没有生成相应的dll文件。

观察编译过程中的output。

(\test.dll) does not match the Linker's OutputFile property value (\Release\test.exe). This may cause your project to build incorrectly. To correct this, please make sure that $(OutDir), $(TargetName) and $(TargetExt) property values match the value specified in %(Link.OutputFile).

选择项目(Project)->属性(Properties)-> Linker -> General ->Output File ->选择 inherit from parent or project defaults

Rebuild重新生成,成功生成dll和lib文件,在C#中调用成功

调用可能出现如下错误

Additional information: 对 PInvoke 函数“Aes!Aes.Program::func1”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

使用如下示例:

[DllImport("test.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]

具体问题,请Google

4.调用C语言dll中的函数,发现结果不正确

这是dll里,头文件的函数声明:

__declspec(dllimport) int func1(char *ch_1, unsigned int u32_1, unsigned int u32_2, char *ch_2);

其中char *ch_2, 是需要返回的结果字符串,如果用out string,或 ref string声明,会出现错误,改用byte[]。

在C#中对应声明为:

[DllImport("test.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
static extern int func1(string ch_1, uint u32_1, uint u32_2, byte[] ch_2);

根据C#调用dll时的类型转换,char * 对应 string。但是,调用结果不正确。后来同事提醒,尝试将所有char * 全部改用byte[] 替换,调用

结果正确。即:

[DllImport("test.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
static extern int func1(byte[] ch_1, uint u32_1, uint u32_2, byte[] ch_2);

如果有相同情况出现的朋友们,可以试试看。

上一篇:linux中ctime,mtime,atime的区别


下一篇:4、爬虫系列之mongodb