• 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/

  • 相关阅读:
    ASP.NET MVC 5
    Web Components是不是Web的未来
    如何选择高性价比的控件产品
    ASP.NET MVC 5
    ubuntu系统安装
    Ubuntu linux安装完成后隐藏linux磁盘挂载点
    win10 查看本机的激活秘钥
    windows cmd下列出当前目录下的所有文件
    error LNK2005: “找到一个或多个多重定义的符号” 已经在 xxxx.obj 中定义 的解决方法
    架构设计:负载均衡层设计方案(3)——Nginx进阶
  • 原文地址:https://www.cnblogs.com/zhangpengshou/p/1699832.html
Copyright © 2020-2023  润新知