在工控行业中会遇到C#调用C++底层函数的情况,比如机械的运动控制底层提供了C++的DLL,而应用系统是C#语言编写的。
下面尝试编写简单C++函数生成DLL,以及C#调用C++函数
1 简单C++函数编写以及生成DLL
- 1.1 创建C++项目
- 1.2 目录结
- 1.3 头文件 stdafx.h 源码就以下 3行
#include <stdio.h>
#include "stdlib.h"
#include <tchar.h>
- 1.4 函数源码
extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。而被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。
__declspec(dllexport)的目的是为了将对应的函数放入到DLL动态库中。
extern "C" __declspec(dllexport)加起来的目的是为了使用DllImport调用非托管C++的DLL文件。因为使用DllImport只能调用由C语言函数做成的DLL。
#include "stdafx.h"
extern "C" __declspec(dllexport) int Add(int x, int y)
{
return x + y;
}
extern "C" __declspec(dllexport) int Sub(int x, int y)
{
return x - y;
}
extern "C" __declspec(dllexport) int Multiply(int x, int y)
{
return x * y;
}
extern "C" __declspec(dllexport) int Divide(int x, int y)
{
return x / y;
}
- 1.5 修改项目属性为生成DLL
2. C# 调用C++函数
2.1 调用方式1 import dll
2.1.1 定义委托import dll的函数
调用函数可能报错:“调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配
主要原因是c++和c#类型不一致导致的,解决办法是在委托的Dll import语句中加上这一句:
CallingConvention = CallingConvention.Cdecl
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Com.Gaaban.Framwork.Common.Cplus { public class DemoDelegate { [DllImport("CplusDll.dll",CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] public static extern int Add(int x, int y); [DllImport("CplusDll.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] public static extern