C#调用C++方法介绍
简介
C#是一种高级编程语言,而C++是一种中级编程语言,在底层处理方面有着突出的优势。将C++模块集成到C#应用程序中,可以利用C++的性能和底层优势来完成一些高性能任务。在实际应用中,使用C#调用C++模块的场景非常普遍,例如Windows API和某些组件库都是基于C++编写的,但是由于其底层特性和页面优化等方面,利用C#调用C++方法并不是一件容易的事情。
方式
C#调用C++的方法比较有会有很多,由于C#对COM接口的支持,可以通过COM技术来实现,也可以通过PInvoke来实现,本文主要介绍使用PInvoke来调用C++库的方法。
PInvoke
PInvoke(Platform Invocation Services)是一种机制,允许C#应用程序调用非托管API,在.NET Framework中,使用DllImport属性可以将非托管函数定义导入到C#应用程序中。
踩坑
在使用PInvoke的过程中,由于C#和C++之间的数据类型存在差异,需要使用Marshaling技术来进行数据类型转换,对应的函数的参数需要有MarshalAs特性来指定数据类型转换方式。
示例
以下为使用PInvoke调用C++库中的函数的示例:
示例1:调用C++ DLL
前提条件:
-
准备一个C++ DLL程序
-
确认C++代码中包含导出函数
__declspec(dllexport) bool GetProcessInfo(uint32_t processId, ProcessInfo& processInfo)
{
if (processId == 0)
{
//error handling code.
return false;
}
//查询进程详细信息
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
if (hProcess == nullptr)
{
//error handling code.
return false;
}
//调用GetProcessInfo()函数,获取进程信息
return GetProcessInfo(hProcess, processInfo);
}
使用C#调用该DLL文件:
using System;
using System.Runtime.InteropServices;
namespace CallCPlusPlusDLL
{
//与C++ DLL函数参数对应
[StructLayout(LayoutKind.Sequential)]
public struct ProcessInfo
{
public string exePath;
public string processName;
public uint32_t processId;
public uint32_t parentProcessId;
}
class Program
{
//导入C++库函数
[DllImport("CPlusPlusDLL.dll")]
public static extern bool GetProcessInfo(UInt32 processId, ref ProcessInfo processInfo);
static void Main(string[] args)
{
ProcessInfo info = new ProcessInfo
{
processId = 3095
};
bool result = GetProcessInfo(info.processId, ref info);
if (result)
{
Console.WriteLine($"Process Name: {info.processName}, Exe Path: {info.exePath}");
}
else
{
Console.WriteLine("Get Process Info Error!");
}
Console.ReadKey();
}
}
}
示例2:调用C++动态链接库中的WinAPI函数
使用IntPtr获取WinAPI函数首地址,使用Marshal.GetDelegateForFunctionPointer()将首地址转换为委托,并执行委托。
using System;
using System.Runtime.InteropServices;
namespace CallWinAPIDLL
{
class Program
{
//获取WinAPI函数首地址
[DllImport("User32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
static void Main(string[] args)
{
//获取控制台窗口句柄
IntPtr hWnd = GetConsoleWindow();
//获取设备环境DC
IntPtr hDC = GetDC(hWnd);
//创建委托类型
delegate void DelegateType();
//获取函数首地址
IntPtr funcAddress = GetProcAddress(GetModuleHandle("User32.dll"), "ReleaseDC");
//将函数首地址转换为委托类型
DelegateType func = (DelegateType)Marshal.GetDelegateForFunctionPointer(funcAddress, typeof(DelegateType));
//执行函数
func();
Console.ReadKey();
}
//获取控制台窗口句柄
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetConsoleWindow();
//获取模块首地址
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string moduleName);
//获取函数首地址
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
}
}
这两个示例介绍了C#调用C++的两种场景,并提供了详细的代码实现。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c#调用c++方法介绍,window api - Python技术站