分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
1, HWND <-> IntPtr
public staticexternbool Get_Msg_Test(IntPtr hwnd);
//hwnd为C#窗体的句柄
extern "C" __declspec(dllexport)bool Get_Msg_Test(HWND hwnd)
代码:
C#
[DllImport("Spy.dll",EntryPoint="Get_Msg_Test",CallingConvention =CallingConvention.Cdecl)] public static extern bool Get_Msg_Test(IntPtr hwnd);private void FrmMain_Load(object sender, EventArgs e) { try { Get_Msg_Test(this.Handle); } catch (System.Exception ex) { //程序收到C++发过来的消息后,此处有异常 } } //用户自定义消息 public const int WM_USER = 0x0400; public const int WM_TEST = WM_USER + 1;protected override void WndProc(ref Message m) { switch (m.Msg) { //旺旺最后一条聊天记录消息 case WM_TEST: LParamDataSruct lparam = (LParamDataSruct)m.GetLParam(typeof(LParamDataSruct)); String msg = lparam.lParamData;//此处能得到C++ DLL发送的消息内容 break; default: break; } base.WndProc(ref m); } /// <summary> /// Message 接收GetLParam方法返回值 /// LParamData返回内容与LParamData结构体相同 /// </summary> public struct LParamDataSruct { public String lParamData; }
C++
#define WM_TEST WM_USER+1//自定义消息struct LParamDataSruct{ public: char* lParamData; //要发送的信息};//hwnd为C#窗体的句柄extern "C" __declspec(dllexport) bool Get_Msg_Test(HWND hwnd){ LParamDataSruct lparam; char* test = "This is test MSG 哈哈。"; lparam.lParamData = test; ::SendMessage(hwnd,WM_TEST,wPARAM,(LPARAM)&lparam); return true;}
2,HBITMAP <-> IntPtr
C++:
HBITMAP DvrControl::GetImage() { // TODO: Add your control notification handler code here if(m_pDvr->get_Image()) memcpy(m_pBuff,m_pDvr->get_Image(),(m_nWidth*m_nHeight*2)); else memset(m_pBuff,0,m_nWidth*m_nHeight*2); //hBmp = m_pSnapshot->CreateBitmapFromYUV(this->m_hWnd,m_pBuff,m_nWidth,m_nHeight,&bi,m_nHalf); hBmp = m_pSnapshot->CreateBitmapFromYUV(NULL, m_pBuff, m_nWidth, m_nHeight, bi, m_nHalf); /*CClientDC dc(CWnd* cwindow); CDC dcmem; if(hBmp){ dcmem.CreateCompatibleDC(&dc); dcmem.SelectObject(hBmp); if(m_nHalf) dc.BitBlt(0,0,m_nWidth*2,m_nHeight*2,&dcmem,0,0,SRCCOPY); else dc.BitBlt(0,0,m_nWidth,m_nHeight,&dcmem,0,0,SRCCOPY); DeleteDC(dcmem); DeleteObject(hBmp); } */ return hBmp;}
C#:
// P/Invoke per TuaDllWrapper.dll://// extern "C" HBITMAP __stdcall GetSomeImage(void);//[DllImport("TuaDllWrapper.dll")]static extern IntPtr GetSomeImage();
微软的.NET框架的优点之一是它提供了独立于语言的开发平台。你可以在VB、C++、C#等语言中编写一些类,而在其它语言中使用(源于.NET中使用了CLS),你甚至可以从另一种语言编写的类中继承。但是你要是想调用以前的非托管DLL,那又会怎么样呢?你必须以某种方式将.NET对象转换为结构体、char *、函数指针等类型。这也就是说,你的参数必须被marshal(注:不知道中文名称该叫什么,英文中指的是为了某个目的而组织人或事物,参见这里,此处指的是为了调用非托管函数而进行的参数转换)。
C#中使用DLL函数之前,你必须使用DllImport声明要调用的函数:
public class Win32 {
[DllImport("User32.Dll")]
public static extern void SetWindowText(int h, String s);
// 函数原型为:BOOL SetWindowText(HWND hWnd, LPCTSTR lpString);
}
DllImport告诉编译器被调函数的入口在哪里,并且将该入口绑定到类中你声明的函数。你可以给这个类起任意的名字,我给它命名为Win32。你甚至可以将类放到命名空间中,具体参见图一。要编译Win32API.cs,输入:
csc /t:library /out:Win32API.dll Win32API.cs
这样你就拥有了Win32API.dll,并且你可以在任意的C#项目中使用它:
using Win32API;
int hwnd = // get it...
String s = "I'm so cute."
Win32.SetWindowText(hwnd, s);
编译器知道去user32.dll中查找函数SetWindowText,并且在调用前自动将String转换为LPTSTR (TCHAR*)。很惊奇是吧!那么.NET是如何做到的呢?每种C#类型有一个默认的marshal类型,String对应LPTSTR