美文网首页
C#调用C语言的方法

C#调用C语言的方法

作者: Matsn | 来源:发表于2021-10-27 10:44 被阅读0次

    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);  //手动释放内存空间
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:C#调用C语言的方法

          本文链接:https://www.haomeiwen.com/subject/mhxenltx.html