C#動態調用非託管dll)

來源:互聯網
上載者:User

嘗試著在C#下調用以前Delphi寫的一些DLL,基本實現動態調用,傳入回呼函數,及調用帶結構數組指標作為參數的函數.

     雖然DllImport可以方便的靜態調用DLL的函數,但在.net2.0中新增加了一個Marshal.GetDelegateForFunctionPointer 方法,可以將非託管函數指標轉換為委託。 有了這個方法就可以用三個Windows API函數即:Loadlibrary,GetProcAddress和Freelibrary來實現動態調用DLL了.下面是實現DLL動態調用的靜態類

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

using System.Data;

 

namespace Test

{

    /// <summary>

    /// DLL載入類

    /// </summary>

    internal class DynamicLoadDll

    {

        [DllImport("Kernel32")]

        public static extern int GetProcAddress(int handle, String funcname);

 

        [DllImport("Kernel32")]

        public static extern int LoadLibrary(String funcname);

 

        [DllImport("Kernel32")]

        public static extern int FreeLibrary(int handle);

 

 

        public static Delegate GetAddress(int dllModule, string functionname, Type t)

        {

            int addr = GetProcAddress(dllModule, functionname);

            if (addr == 0)

                return null;

            else

                return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t);

        }

}

 

Public class referDll

{

private int m_hDLL = 0; //DLL控制代碼
  private delegate int ShowForm(IntPtr aHandle);
  private ShowForm m_ShowForm;
  private const string DLLNAEM = "XXX.dll";

  m_hDLL = DllLoader.LoadLibrary(DLLNAEM);
  if (m_hDLL == 0)
    { MessageBox.Show("載入失敗!")
       return;
    }
 m_ShowForm = (ShowForm) DllLoader.GetAddress(m_hPacsview, "ShowForm", typeof (ShowForm));
//使用ShowForm
 if (m_ShowForm != null)
                m_ShowForm(iHandle);
//卸載DLL
DllLoader.FreeLibrary(m_hDLL);

}

}

接著說說如何調用DLL中帶結構數組指標作為參數的函數.在原來Delphi中定義如下:

//一個結構定義如下
TStudyRec  = Record
       UID  : Array[0..127] of Char;
  end;

TCharArray=Array[0..49] of TStudyRec;

//在DLL中有如下函數 其中AStudys為TCharArray的指標
 function Open(AStudys: Pointer): HRESULT; StdCall;

要在C#裡正常調用,首先要定義出一個相同的結構

private struct StudyRec
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string UID; //名稱  
}

接著聲明一個委託
private delegate int Open(IntPtr aStudys);
從DLL得到委託執行個體

private Open m_Open = (Open) DllLoader.GetAddress(m_hDLL, "Open", typeof (Open)); //m_hDLL為DLL指標

到此為止終於在C#裡定義出相同的結果及函數了,下面就是要調用了,因為結構數組是要給非託管的DLL使用的,因此最關鍵的一點是要用Marshal.AllocHGlobal來分配好非託管記憶體,把結構數組放到記憶體中去,再把記憶體指標當作參數調用就OK啦

StudyRec[] arrStudyRec = new StudyRec[50];
  int isize = Marshal.SizeOf(typeof (StudyRec));
  IntPtr parrStudyRec = Marshal.AllocHGlobal(Marshal.SizeOf(isize*50));
  int run = (int) parrStudyRec;

 for (int i = 0; i < 50; i++)
{

arrStudyRec[i].UID =  i.tostring();//這裡只是類比,所以直接把i當作UID了
Marshal.StructureToPtr(arrStudyRec[i], (IntPtr) run, false);
run += isize;

}

 m_Open(parrStudyRec);

 

轉自:http://zhouweigang01.blog.163.com/blog/static/934090720095493459311/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.