C#动态调用非托管DLL

转载 2007年09月24日 17:06:00

尝试着在C#下调用以前Delphi写的一些DLL,基本实现动态调用,传入回调函数,及调用带结构数组指针作为参数的函数.

     虽然DllImport可以方便的静态调用DLL的函数,但在.net2.0中新增加了一个Marshal.GetDelegateForFunctionPointer 方法,可以将非托管函数指针转换为委托。 有了这个方法就可以用三个Windows API函数即:LoadlibraryGetProcAddressFreelibrary来实现动态调用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中有如下函数 其中AStudysTCharArray的指针
 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_hDLLDLL指针


到此为止终于在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);

 

C#调用托管DLL与非托管DLL

DLL之前使用过几次,但是最近使用时,又出各种问题。最后弄到晚上十二点多了,看到网上一个创建DLL的图解教程,按上面的讲解,成功实现了C#调用自己创建的DLL。之所以耗了这么久时间,是因为我本想凭自己...

C# 中如何调用DLL文件(分两种情况,托管与非托管)

C# 中如何调用DLL文件? 2010-11-28 08:46yanghao717  分类:C#/.NET | 浏览 14452 次  C#编程 我在网上找了好久都没看明白,所以来这...

C#调用C++的dll两种方法(托管与非托管)

C#调用C++的方式分为两种:(1)非托管的方式进行调用;(2)采用托管的方式进行调用。 一、使用非托管类调用C++的dll。 1、首先在vs2010新建项目选择win32应用程序,并设置为DLL,如...

托管DLL和非托管DLL的区别

首先解释一下,托管DLL和非托管DLL的区别。狭义解释讲,托管DLL就在Dotnet环境生成的DLL文件。非托管DLL不是在Dotnet环境生成的DLL文件。      托管DLL文件,可以在D...

托管非托管Dll动态调用

最近经常看到有人问托管非托管Dll调用的问题。对于动态库的调用其实很简单。网上很多代码都实现了Dll的静态调用方法。我主要谈论下动态库的动态加载。对于托管动态库,实现动态加载很简单。/Files/dw...

C#动态调用非托管DLL(一)

         尝试着在C#下调用以前Delphi写的一些DLL,基本实现动态调用,传入回调函数,及调用带结构数组指针作为参数的函数.     虽然DllImport可以方便的静态调用DLL的函数,...
  • awin
  • awin
  • 2007年02月01日 21:50
  • 1302

C#中调用非托管的DLL及参数传递

    微软的.NET框架的优点之一是它提供了独立于语言的开发平台。你可以在VB、C++、C#等语言中编写一些类,而在其它语言中使用(源于.NET中使用了CLS),你甚至可以从另一种语言编写的类中继承...

C#调用非托管代码(转)

C#调用非托管代码(转) 在.net 编程环境中,系统的资源分为托管资源和非托管资源。   对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的 只是了解...

使用了非托管的第三方库的c++动态库在c#中的调用

         在c#中使用c++动态库,一般情况下有两种有两种方法,第一种是使用c++\CLI,这种方法比较直观,但是需要花费时间学习c++\CLI,比较简单的方法是PInvoke,但是这种...

_tcstol 字符串到数字的转化

先看MSDN上对_tcstol的解释 1、在不同平台上的不同形式 TCHAR.H Routine _UNICODE & _MBCS Not Defined _MBCS Def...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C#动态调用非托管DLL
举报原因:
原因补充:

(最多只允许输入30个字)