C#调用C/C++

C#调用C/C++

  • 前言
  • DLL的生成
  • C#控制台调用DLL以及平台问题
  • 遇到的一些坑

前言

    最近做课程实践,用C#做可视化,C/C++来完成功能实现部分,记录下调用的简单步骤和一些坑。

DLL的生成

    要使C/C++的代码能在C#中执行,需要先将C/C++的代码文件生成DLL文件,具体操作:
    通过VS2019创建C++下的动态链接库项目
C#调用C/C++_第1张图片
    生成项目后,在解决方案里,IDE会帮你生成必须的文件,着重于pch.h和pch.cpp这两个文件
C#调用C/C++_第2张图片
    打开pch.cpp这个文件,在给定的模板内,我们可以编写C/C++代码

// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"
#include
void sayHello()
{
	printf("Hello C# and C/C++\n");
}
// 当使用预编译的头时,需要使用此源文件,编译才能成功。

    接下来打开pch.h这个文件,在给定的模板内,声明我们要调用的函数

// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。

#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"
extern "C" _declspec(dllexport)  void sayHello();
#endif //PCH_H

    接下来点击生成解决方案
在这里插入图片描述
    完成后会显示成功
C#调用C/C++_第3张图片

C#控制台调用DLL以及平台问题

    先新建一个C#控制台程序测试一下,首先需要声明从哪个DLL中调用哪个函数,具体如下

using System;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    class Program
    {
        [DllImport("D:\\Project\\Dll\\TestDL\\Debug\\TestDL.dll")]
        public static extern void sayHello();

        static void Main(string[] args)
        {
            sayHello();
        }
    }
}

    执行该程序,结果报错
C#调用C/C++_第4张图片
    具体原因在于DLL所生产的平台不对,重新打开DLL文件项目,进入项目->属性,会发现其平台是32位的
C#调用C/C++_第5张图片

C#调用C/C++_第6张图片
    点击配置管理器,修改成x64后,再次生成DLL,然后需要注意的是,这次生成的DLL文件并不位于"项目名\debug"内了,而是在"项目名\x64\debug"内,所以需要修改路径,然后再次运行C#程序。
C#调用C/C++_第7张图片

using System;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    class Program
    {
        [DllImport("D:\\Project\\Dll\\TestDL\\x64\\Debug\\TestDL.dll")]
        public static extern void sayHello();

        static void Main(string[] args)
        {
            sayHello();
        }
    }
}

    结果成功输出
C#调用C/C++_第8张图片
    如果要使用C#窗体应用程序,就无需在x64下进行,按照原来的32位即可。调用方法相同,不多赘述。

遇到的一些坑

    如果你使用了传参,或者带有返回值的函数,需要注意以下

  • 一是C/C++与C#的类型对应关系,C/C++中的unsigned short并不对应于C#中的ushort类型,而是UInt16这个类型,以及int[]传入C/C++,要用int* 接收,此外要接收C/C++的字符串(char*)需要用C#的IntPtr这个类型接收。具体其他类型对应,可百度。
  • 二是当你要传参或接收返回值时,IDE会对你进行中断提醒,大意为可能会出现类型错误,如果你能确定类型对应没有错,请选择屏蔽该中断,这样你运行程序时就不会突然中断一下。

你可能感兴趣的:(九九八十一难,c#,c++,dll)