新建项目->Visual C++->win32->Win32项目->输入项目名称->next->应用程序类型选dll,附加选项选上“导出符号”,添加公共头文件视情况可以加上MFC->完成。
此时生成的项目有示例代码,可以在原来的代码上修改。
需要注意的是:
#define 项目名_API extern "C" _declspec(dllimport)
原来的宏定义可能不包括extern "C",加上可以被C#等语言调用。
在C#中调用的时候,把dll放到目录中,
using System.Runtime.InteropServices;
然后
[DllImport("2_channel.dll")]
public static extern void run();
即可
在使用lib静态链接库时,需要增加程序的依赖性。
常见的类型转换:
基本类型:
Handle | IntPtr |
Hwnd | IntPtr |
int* | ref int |
int& | ref int |
void* | IntPtr |
unsigned char* | ref byte |
BOOL | bool |
DWORD | int 或 uint(int 更常用一些) |
C++(Win 32) | C# |
char** | 作为输入参数转为char[],通过Encoding类对这个string[]进行编码后得到的一个char[] |
作为输出参数转为byte[],通过Encoding类对这个byte[]进行解码,得到字符串 | |
C++ Dll接口: | |
void CplusplusToCsharp(in char** AgentID, out char** AgentIP); | |
C#中的声明: | |
[DllImport("Example.dll")] | |
public static extern void CplusplusToCsharp(char[] AgentID, byte[] AgentIP); | |
C#中的调用: | |
Encoding encode = Encoding.Default; | |
byte[] tAgentID; | |
byte[] tAgentIP; | |
string[] AgentIP; | |
tAgentID = new byte[100]; | |
tAgentIP = new byte[100]; | |
CplusplusToCsharp(encode.GetChars(tAgentID), tAgentIP); | |
AgentIP[i] = encode.GetString(tAgentIP,i*Length,Length); |
枚举类型 | Win32: |
BOOL MessageBeep(UINT uType // 声音类型); 其中的声音类型为枚举类型中的某一值。 | |
C#: | |
用户需要自己定义一个枚举类型: | |
public enum BeepType | |
{ | |
SimpleBeep = -1, | |
IconAsterisk = 0x00000040, | |
IconExclamation = 0x00000030, | |
IconHand = 0x00000010, | |
IconQuestion = 0x00000020, | |
Ok = 0x00000000, | |
} | |
C#中导入该函数: | |
[DllImport("user32.dll")] | |
public static extern bool MessageBeep(BeepType beepType); | |
C#中调用该函数: | |
MessageBeep(BeepType.IconQuestion); |
结构类型 | Win32: |
使用结构指针作为参数的函数: | |
BOOL GetSystemPowerStatus( | |
LPSYSTEM_POWER_STATUS lpSystemPowerStatus | |
); | |
Win32中该结构体的定义: | |
typedef struct _SYSTEM_POWER_STATUS { | |
BYTE ACLineStatus; | |
BYTE BatteryFlag; | |
BYTE BatteryLifePercent; | |
BYTE Reserved1; | |
DWORD BatteryLifeTime; | |
DWORD BatteryFullLifeTime; | |
} SYSTEM_POWER_STATUS, *LPSYSTEM_POWER_STATUS; | |
C#: | |
用户自定义相应的结构体: | |
struct SystemPowerStatus | |
{ | |
byte ACLineStatus; | |
byte batteryFlag; | |
byte batteryLifePercent; | |
byte reserved1; | |
int batteryLifeTime; | |
int batteryFullLifeTime; | |
} | |
C#中导入该函数: | |
[DllImport("kernel32.dll")] | |
public static extern bool GetSystemPowerStatus( | |
ref SystemPowerStatus systemPowerStatus); | |
C#中调用该函数: | |
SystemPowerStatus sps; | |
….sps初始化赋值…… | |
GetSystemPowerStatus(ref sps); |
字符串 | 对于字符串的处理分为以下几种情况: |
1、 字符串常量指针的处理(LPCTSTR),也适应于字符串常量的处理,.net中的string类型是不可变的类型。 | |
2、 字符串缓冲区的处理(char*),即对于变长字符串的处理,.net中StringBuilder可用作缓冲区 | |
Win32: | |
BOOL GetFile(LPCTSTR lpRootPathName); | |
C#: | |
函数声明: | |
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] | |
static extern bool GetFile ( | |
[MarshalAs(UnmanagedType.LPTStr)] | |
string rootPathName); | |
函数调用: | |
string pathname; | |
GetFile(pathname); | |
备注: | |
DllImport中的CharSet是为了说明自动地调用该函数相关的Ansi版本或者Unicode版本 | |
变长字符串处理: | |
C#: | |
函数声明: | |
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] | |
public static extern int GetShortPathName( | |
[MarshalAs(UnmanagedType.LPTStr)] | |
string path, | |
[MarshalAs(UnmanagedType.LPTStr)] | |
StringBuilder shortPath, | |
int shortPathLength); | |
函数调用: | |
StringBuilder shortPath = new StringBuilder(80); | |
int result = GetShortPathName( | |
@"d:\test.jpg", shortPath, shortPath.Capacity); | |
string s = shortPath.ToString(); |
struct | 具有内嵌字符数组的结构: |
Win32: | |
typedef struct _TIME_ZONE_INFORMATION { | |
LONG Bias; | |
WCHAR StandardName[ 32 ]; | |
SYSTEMTIME StandardDate; | |
LONG StandardBias; | |
WCHAR DaylightName[ 32 ]; | |
SYSTEMTIME DaylightDate; | |
LONG DaylightBias; | |
} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION; | |
C#: | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] | |
struct TimeZoneInformation | |
{ | |
public int bias; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] | |
public string standardName; | |
SystemTime standardDate; | |
public int standardBias; | |
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] | |
public string daylightName; | |
SystemTime daylightDate; | |
public int daylightBias; | |
} |
具有回调的函数 | Win32: |
BOOL EnumDesktops( | |
HWINSTA hwinsta, // 窗口实例的句柄 | |
DESKTOPENUMPROC lpEnumFunc, // 回调函数 | |
LPARAM lParam // 用于回调函数的值 | |
); | |
回调函数DESKTOPENUMPROC的声明: | |
BOOL CALLBACK EnumDesktopProc( | |
LPTSTR lpszDesktop, // 桌面名称 | |
LPARAM lParam // 用户定义的值 | |
); | |
C#: | |
将回调函数的声明转化为委托: | |
delegate bool EnumDesktopProc( | |
[MarshalAs(UnmanagedType.LPTStr)] | |
string desktopName, | |
int lParam); | |
该函数在C#中的声明: | |
[DllImport("user32.dll", CharSet = CharSet.Auto)] | |
static extern bool EnumDesktops( | |
IntPtr windowStation, | |
EnumDesktopProc callback, | |
int lParam); |
该表对C#中调用win32函数,以及c++编写的dll时参数及返回值的转换做了一个小的总结,如果想进一步了解这方面内容的话,可以参照msdn中“互操作封送处理”一节。