C#调用DLL时出现的错误(个人总结向)
C#调用DLL时出现的错误前言1.环境配置问题1.1 无法加载*.dll,找不到指定的模块2.DLL程序问题2.1 无法在dll中找到入口点2.2 在C#中捕捉DLL中函数异常2.3 Invalid address specified to RtlValidateHeap2.4 DLL编译3.C#调用问题3.1 尝试读取或写入受保护的内存3.2 C# 调用dll出现托管问题3.3 参数不一致3.4
C#调用DLL时出现的错误
前言
在做实验室的工作中,出现了很多次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)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)