zoukankan      html  css  js  c++  java
  • C#动态调用非托管dll(转)

    尝试着在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/

  • 相关阅读:
    Codeforces 877 C. Slava and tanks
    Codeforces 877 D. Olya and Energy Drinks
    2017 10.25 NOIP模拟赛
    2017 国庆湖南 Day1
    UVA 12113 Overlapping Squares
    学大伟业 国庆Day2
    51nod 1629 B君的圆锥
    51nod 1381 硬币游戏
    [JSOI2010]满汉全席
    学大伟业 2017 国庆 Day1
  • 原文地址:https://www.cnblogs.com/zhangpengshou/p/1699832.html
Copyright © 2011-2022 走看看