首先用DllImport导入动态库文件(DLL)。
[System.Runtime.InteropServices.DllImport("ALComm.dll")]
我这里主要说的是,vc++中的各种变量类型,在C#中用什么样的类型代替。
数字参数
首先用vc++编写一个DLL,打开VS2010,选择新建WIN32工程,在下一步的时候,选择建立DLL。
项目命名"test".
接着进入test.cpp里编写一个函数,如下:
extern "C" __declspec(dllexport) ULONG Add(DWORD a,int b)
{
return a+b;
}
然后C#里调用,如下:
[System.Runtime.InteropServices.DllImport("test.dll")]
public static extern int Add(int a, int b);
private void button1_Click(object sender, EventArgs E)
{
int a = Add(5, 6);
MessageBox.Show(a.ToString());
}
结果如下:
可以看到,在VC++里,像DWORD,ULONG,USHORT之类的数字类型在C#中都可以用
int代替,一般情况下是不会出错的,只要在两种数据类型的公共范围就没问题。(变量所占字节数量是必须一致).
可以看到DWORD最终的定义是:unsigned long,ULONG也是一样。
但要传递的数据,如果超过了int类型,那就用uint类型吧。
字符和字符串参数
单个char类型,直接定义就可以了,C#和VC++中都有char类型。
关于字符串,首先来编写一个DLL,代码如下:
extern "C" __declspec(dllexport)void msg(WCHAR str1[],WCHAR *str2)
{
MessageBox(NULL,str1,str2,MB_OK);
}
MessageBox里的第二个参数和第三个参数是LPCWSTR类型的,也就宽字符类型(VS里)
在VS里,你也可以指定单字符的(LPCSTR类型),如:
extern "C" __declspec(dllexport)void msg(char str1[],char *str2)
{
MessageBoxA(NULL,str1,str2,MB_OK);
}
在C#调用就是这样:
[System.Runtime.InteropServices.DllImport("test.dll",CharSet=System.Runtime.InteropServices.CharSet.Unicode)]
public static extern void msg(string str1,string str2);
private void button1_Click(object sender, EventArgs E)
{
msg("用window API来弹出提示框","这是标题");
}
如果DLL中的函数参数是宽字符,那么CharSet就要指定Unicode
事实上对于字符串类型,在C#中用string来代替,把字符传递过去是没问题的,但用string来获取,就
会有问题。
要用这种方式获取:DLL
extern "C" __declspec(dllexport)char * GetTitle(HWND wnd)
{
char str2[100];
::GetWindowTextA(wnd,str2,10);
return str2;
}
C#
[System.Runtime.InteropServices.DllImport("test.dll")]
public static extern string GetTitle(IntPtr wnd);
private void button1_Click(object sender, EventArgs E)
{
string str2=GetTitle(this.Handle);
MessageBox.Show(str2);
}
但不能这样:
C#中传递一个string类型过去,然后DLL里,给它赋值,这边再取出。
如果要实现这种功能的话,在C#中一律用StringBuilder代替。看一个API示例函数,如下:
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "GetWindowText")]
public static extern int GetTitle(
IntPtr hwnd,
StringBuilder lpString,
int cch
);
调用:
private void button1_Click(object sender, EventArgs e)
{
StringBuilder lpString = new StringBuilder(255);
GetTitle(this.Handle, lpString, 255);
MessageBox.Show(lpString.ToString());
上面导入时,填了一个参数EntryPoint,指定入口函数,这样在下面可以给函数取一个别名GetTitle
句柄
句柄最终的定义是指针类型,所以在C#中,只要有句柄,一律用IntPtr代替
数字指针类型
可用ref引用参数代替,(LPDWORD等)如:
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int ProccessId);
调用:
int pid = 0;
GetWindowThreadProcessId(this.Handle, ref pid);
if (System.Diagnostics.Process.GetCurrentProcess().Id == pid)
MessageBox.Show("Yes,Success!");