C 调用C++的Dll dll DLL 类型之间转换笔记

本文介绍了在C#中如何调用C++的DLL,涉及到HWND与IntPtr的转换、结构体和回调函数的处理、以及DllImport的使用方法。文章详细讲解了不同类型参数的封送和转换,包括HWND、结构体、回调函数的调用,并给出了具体的代码示例。此外,还提到了平台调用的原理和MarshalAsAttribute的作用。
摘要由CSDN通过智能技术生成

分享一下我老师大神的人工智能教程!零基础,通俗易懂!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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值