1. DllImport异常: Unable to find an entry point named 'xxxxxx'
指定的函数没有导出,检查c/c++的函数是否导出
2. System.BadImageFormatException: 试图加载格式不正确的程序。
-
引入的dll动态库和 exe程序的平台不一致。
-
c#默认的解决方案平台是AnyCPU ,如果在 x64的操作系统上运行,则是调用x64的标准库,如果c/c++默认的平台是x86,那么就会在运行的时候报该错误,
-
解决方案:在c#程序指定与c/c++动态库相同的平台即可。
3. c语言函数导出:
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
_declspec(dllexport) //通过C语言格式导出函数,如果是在C++项目中,导出C语言格式函数需要 extern "C"
int Add(int num1, int num2, int* pSum)
{
if (pSum == NULL)
{
pSum = (int*)malloc(sizeof(int));
if (pSum == NULL) {
return -1;
}
}
*pSum = num1 + num2;
return 0;
}
4. 在C#中导入C语言动态库, 并调用方法:
-方法1 利用C#的 ref/out关键字来代替指针的输出,这个一般针对值类型(ValueType)的指针
```c#
public class Class2
{
private const string dllPath = @"xxxx.dll";
[DllImport(dllPath, EntryPoint = "Add", CallingConvention = CallingConvention.Cdecl)] //Cdecl表示C语言格式导出的函数, EntryPoint 指定导出函数的函数名
public static extern int Add1(int num1, int num2, out int sum); //Add1 如果没有指定EntryPoint,则必须与导出函数名一致
public static void TestAdd()
{
Class2.Add1(100, 100, out int sum);
Console.WriteLine(sum);
}
}
```
-方法2 直接在c#非托管堆内存中开辟空间,并将非托管堆内存地址传入方法,由C语言在该内存中写入数据,c#再去非托管堆中获取内存中的数据。
public class Class2
{
private const string dllPath = @"xxxx.dll";
[DllImport(dllPath, EntryPoint = "Add", CallingConvention = CallingConvention.Cdecl)] //Cdecl表示C语言格式导出的函数, EntryPoint 指定导出函数的函数名
public static extern int Add2(int num1, int num2, IntPtr sum); //Add1 如果没有指定EntryPoint,则必须与导出函数名一致
public static void TestAdd()
{
IntPtr intPtr = Marshal.AllocHGlobal(sizeof(int)); //在非托管堆上开辟内存空间,大小为sizeof(int)
if(intPtr != IntPtr.Zero && 0 == Class2.Add2(100, 100, intPtr))
{
int sum1 = Marshal.PtrToStructure<int>(intPtr); //从非托管堆地址中,读取一个int空间的值
Console.WriteLine(sum1);
Marshal.FreeHGlobal(intPtr); //手动释放内存空间
}
}
}
网友评论