新建项目->VisualC++->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静态链接库时,需要增加程序的依赖性。
常见的类型转换:
基本类型:
HandleIntPtrHwndIntPtrint*ref intint&ref intvoid*IntPtrunsigned char*ref byteBOOLboolDWORDint 或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( IntPtrwindowStation, EnumDesktopProc callback, int lParam);该表对C#中调用win32函数,以及c++编写的dll时参数及返回值的转换做了一个小的总结,如果想进一步了解这方面内容的话,可以参照msdn中“互操作封送处理”一节。