前言

在做实验室的工作中,出现了很多次C#调用DLL的错误,做下总结.
由于是个人向,解决方案难免缺乏鲁棒性,仅供参考,并不全面

保险的做法:编译的DLL放到项目下和System里,都放

1.环境配置问题

1.1 无法加载*.dll,找不到指定的模块

0.一般会在更换新电脑时出现该问题

1.用Dependency Walker 2.2或其他dll查看器打开*.dll
2.查看该电脑缺失(显示红色的)的*.dll的依赖库并下载,比如dll中调用了CGAL库,新电脑上缺失相关依赖库,则需要下载如下dll在这里插入图片描述

3.把*.dll以及依赖库放到C://Windows/System32(x64)或C://Windows/SysWow64(x86)里
4.最好重启下

2.DLL程序问题

2.1 无法在dll中找到入口点

示例:
在这里插入图片描述
规范DLL函数前缀
一般来说前缀为:extern “C” _declspec(dllexport)
更详细的可以参考
EntryPointNotFoundException

2.2 在C#中捕捉DLL中函数异常

1.app.config 添加:

<configuration>
	<runtime>
		<legacyCorruptedStateExceptionsPolicy enabled="true"/>
	</runtime>
<configuration>

2.函数前加
[HandleProcessCorruptedStateExceptions]

2.3 Invalid address specified to RtlValidateHeap

在这里插入图片描述
重复使用同一stringstream时,应该使用str()初始化

2.4 DLL编译

一定要用Release,Debug太慢了!

3.C#调用问题

3.1 尝试读取或写入受保护的内存

在这里插入图片描述
传入的数组长度开的太小了

3.2 C# 调用dll出现托管问题

在这里插入图片描述
DLLImport后面加入 CallingConvention = CallingConvention.Cdecl

3.3 参数不一致

例如对于dll中的函数
extern “C” _declspec(dllexport) int add(int a,int b)
{
return a+b;
}
以及C#中的函数
[DllImport("*…dll")]
public static extern int add(long a,long b)
调用add(1,2),返回1

3.4 调用带传出数组函数

带传出数组:
C++不能直接传出数组,只传出数组指针,

void __declspec(dllexport) test(const int M, const int n[], int *N) 
{ 
	
} 

对应的C#代码:

[DllImport("*.dll")] 
public static extern void test(int M, int[] n, [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] int[] N); 

4.其他

4.1 warning C4819: 该文件包含不能在当前代码页中表示的字符

Visual Studio 2017 出现warning C4819: 该文件包含不能在当前代码页中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失

解决方案:
1.修改字符编码格式
Visual Studio提供高级保存选项功能,它能指定特定代码文件的编码规范和行尾所使用的换行符。在Visual Studio 2017中,该命令没有默认显示在“文件”菜单中。用户需要手工设置,才能显示该命令。操作方法如下:

(1)单击“工具”|“自定义”命令,弹出“自定义”对话框。
(2)单击“命令”标签,进入“命令”选项卡。
(3)在“菜单栏”下拉列表中,选择“文件”选项。
(4)单击“添加命令”按钮,弹出“添加命令”对话框。
(5)在“类别”列表中,选择“文件”选项;在“命令”列表中,选择“高级保存选项”选项。
(6)单击“确定”按钮,关闭“添加命令”对话框。
(7)选中“控件”列表中的“高级保存选项”选项,单击“上移”或者“下移”按钮,调整该命令的位置。
(8)单击“关闭”按钮,完成“高级保存选项”命令的添加操作。
(9)打开“文件”菜单下的“高级保存选项”,设置编码为ASCII,关闭,然后再设置为unicode(utf-8)

4.2 C++ error LNK2019: 无法解析的外部符号 WinMain

临时将DLL修改为控制台输出时,报错

一,问题描述
MSVCRTD.lib(exe_winmain.obj) : error LNK2019: 无法解析的外部符号 WinMain,该符号在函数 “int __cdecl invoke_main(void)” (?invoke_main@@YAHXZ) 中被引用
CamShift.exe : fatal error LNK1120: 1 个无法解析的外部命令

error LNK2001: unresolved external symbol _WinMain
debug/main.exe:fatal error LNK 1120:1 unresolved externals
error executing link.exe;

二,原因及解决办法
产生这个问题的真正原因是c语言运行时找不到适当的程序入口函数.
一般情况下,如果是windows程序,那么WinMain是入口函数,在VS2017中新建项目为“win32项目”
如果是dos控制台程序,那么main是入口函数,在VS2017中新建项目为“win32控制台应用程序”

而如果入口函数指定不当,很显然c语言运行时找不到配合函数,它就会报告错误。

修改设置适应你的需求

如果是windows程序:

1.菜单中选择 Project->Properties, 弹出Property Pages窗口

2.在左边栏中依次选择:Configuration Properties -> C/C++ -> Preprocessor,然后在右边栏的Preprocessor Definitions对应的项中删除_CONSOLE, 添加_WINDOWS.

3.在左边栏中依次选择:Configuration Properties->Linker->System,然后在右边栏的SubSystem对应的项改为Windows(/SUBSYSTEM:WINDOWS)

如果是控制台程序:

1.菜单中选择 Project->Properties, 弹出Property Pages窗口

2.在左边栏中依次选择:Configuration Properties -> C/C++ -> Preprocessor,然后在右边栏的Preprocessor Definitions对应的项中删除_WINDOWS, 添加_CONSOLE.

3.在左边栏中依次选择:Configuration Properties->Linker->System,然后在右边栏的SubSystem对应的项改为CONSOLE(/SUBSYSTEM:CONSOLE)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐