抛出问题
C#项目要采用第三方的方案实现某个功能,第三方提供了一个C++实现的库Dll库。然鹅,在实现的过程中遇到一系列的问题,最后都搞懂了,现分享下过程,主要问题总结如下:
1、System.DllNotFoundException 解决之路无法加载DLL“xxx.dll”:找不到指定的模块(异常来自HRESULT:0X8007007E) 2、未处理System.BadImageFormatException,试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B) 3、System.EntryPointNotFoundException:Unable to find an entry point named 4、C# 和C++ 数据结构映射(结构体指针)
痛苦的解决过程
① 右键添加引用报如下错误:请确保此文件可访问并且是一个有效的程序集或COM组件
② 按网上说的 regsvr32 dll 还是不通
③ 既然此法不通换个思路,得用DllImport代码导入方式
DllImport代码举例如下(注意int* 用IntPtr ,char* 用string替换)
[DllImport("xxxxxxxx.dll"]
public static extern IntPtr XXXXOpen(string xxxx01, string xxxx02){……};
④ 然鹅,又报错误 无法加载 DLL“xxxx.dll”: 找不到指定的模块
继续度娘,发现有可能是缺少依赖项的情况。下载使用depends.exe查看xxxx.dll的依赖项,分析看,果不其然缺了不少依赖库啊,下载缺失的依赖项到Debug目录下,解决
⑤然鹅,又报错误 System.BadImageFormatException 这个是因为,程序中引用外部dll文件的目标平台的版本x86和x64不一致引起的
⑤然鹅,又报错误 System.EntryPointNotFoundException 原因:在C++函数声明时要将 extern “C” 添加在 DLL 函数声明之前 。 如果不加的话,C++编译为dll之后,函数名会发生变化,会多了一些符如号?@@等,有些参数顺序还会发生变化。可以用DllAnalyzer工具查看dll的输出函数名,发现输出的函数名有所变化,多了@xxx和一些别的奇怪的字符,实际上是因为C++重载机制造成的,使用使用extern "C"关键字即可或者直接把那一长串拷贝过去可以解决!
[DllImport("a.dll",EntryPoint="?F@@YAHXZ")]
public extern static int F();
⑥ 至于C# 和C++ 数据结构映射(结构体指针),参考如下
PS:后面找到有个工具可以自己生成 ===>【CLRInsideOut】C#调用C++DLL结构体或函数声明代码生成工具
struct A{
double a[20];
};
struct B{
double b[20];
int c[10];
};
extern “C” _declspec(dllexport) int abc(
char* filePath,
A* input,
B* output,
int flag
);
[StructLayout(LayoutKind.Sequential)]
public struct A
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType = UnmanagedType.R8)]
public double[] a;
}
[StructLayout(LayoutKind.Sequential)]
public struct B
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType = UnmanagedType.R8)]
public double[] b;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType = UnmanagedType.I4)]
public int[] c;
}
[DllImport("xxx.dll", EntryPoint = "abc", CallingConvention = CallingConvention.Cdecl)]
public static extern int abc(
string filePath,
ref A input,
out B output,
int flag
);
总结
如上就是我遇到的坑及解决方法,希望给有需要的同学有所帮助!!!
参考
VisualStudio关于C#项目Dll的引用几种方式无法加载 DLL“xxxx.dll”: 找不到指定的模块C# 程序运行无法加载 C++ DLL“xxx.dll”:找不到指定的模块C# 提示:无法加载 DLL“XXX.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)depends.exe用法vs2019 实现C#调用c++的dll两种方法(自己写Dll和C#调用加强理解)C#调用C++dll文件 运行提示找不到函数的入口点C#调用C++的DLL找不到入口点以及衍生的相关问题C# 调用C++ dll EntryPointNotFoundException错误
精彩文章
发表评论