抛出问题

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错误

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。