c#里实现dll调用(郁闷版)

      这个是各函数模块,下面将要引用已经编写好的dll了,这个dll是在C++里面编写的
        /// <summary>
        /// 原型是 :HMODULE LoadLibrary(LPCTSTR lpFileName);
        /// </summary>
        /// <param name="lpFileName">DLL 文件名 </param>
        /// <returns> 函数库模块的句柄 </returns>
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);
        /// <summary>
        /// 原型是 : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);
        /// </summary>
        /// <param name="hModule"> 包含需调用函数的函数库模块的句柄 </param>
        /// <param name="lpProcName"> 调用函数的名称 </param>
        /// <returns> 函数指针 </returns>
        [DllImport("kernel32.dll")]
        static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
        /// <summary>
        /// 原型是 : BOOL FreeLibrary(HMODULE hModule);
        /// </summary>
        /// <param name="hModule"> 需释放的函数库模块的句柄 </param>
        /// <returns> 是否已释放指定的 Dll</returns>
        [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]
        static extern bool FreeLibrary(IntPtr hModule);

        public Delegate Invoke(string APIName, Type t)
        {
            IntPtr api = GetProcAddress(hModule, APIName);
            return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);
        }

        /// <summary>
        /// Loadlibrary 返回的函数库模块的句柄
        /// </summary>
        private IntPtr hModule = IntPtr.Zero;
        /// <summary>
        /// GetProcAddress 返回的函数指针
        /// </summary>
        private IntPtr farProc = IntPtr.Zero;
        /// <summary>
        /// 装载 Dll
        /// </summary>
        /// <param name="lpFileName">DLL 文件名 </param>
        public void LoadDll(string lpFileName)
        {
            hModule = LoadLibrary(lpFileName);
            if (hModule == IntPtr.Zero)
                throw (new Exception(" 没有找到 :" + lpFileName + "."));
        }
        //  若已有已装载Dll的句柄,可以使用LoadDll方法的第二个版本:
        public void LoadDll(IntPtr HMODULE)
        {
            if (HMODULE == IntPtr.Zero)
                throw (new Exception(" 所传入的函数库模块的句柄 HMODULE 为空 ."));
            hModule = HMODULE;
        }
        /// <summary>
        /// 获得函数指针
        /// </summary>
        /// <param name="lpProcName"> 调用函数的名称 </param>
        public void LoadFun(string lpProcName)
        { // 若函数库模块的句柄为空,则抛出异常
            if (hModule == IntPtr.Zero)
                throw (new Exception(" 函数库模块的句柄为空 , 请确保已进行 LoadDll 操作 !"));
            // 取得函数指针
            farProc = GetProcAddress(hModule, lpProcName);
            // 若函数指针,则抛出异常
            if (farProc == IntPtr.Zero)
                throw (new Exception(" 没有找到 :" + lpProcName + " 这个函数的入口点 "));
        }
        /// <summary>
        /// 获得函数指针
        /// </summary>
        /// <param name="lpFileName"> 包含需调用函数的 DLL 文件名 </param>
        /// <param name="lpProcName"> 调用函数的名称 </param>
        public void LoadFun(string lpFileName, string lpProcName)
        { // 取得函数库模块的句柄
            hModule = LoadLibrary(lpFileName);
            // 若函数库模块的句柄为空,则抛出异常
            if (hModule == IntPtr.Zero)
                throw (new Exception(" 没有找到 :" + lpFileName + "."));
            // 取得函数指针
            farProc = GetProcAddress(hModule, lpProcName);
            // 若函数指针,则抛出异常
            if (farProc == IntPtr.Zero)
                throw (new Exception(" 没有找到 :" + lpProcName + " 这个函数的入口点 "));
        }

        /// <summary>
        /// 卸载 Dll
        /// </summary>
        public void UnLoadDll()
        {
            FreeLibrary(hModule);
            hModule = IntPtr.Zero;
            farProc = IntPtr.Zero;
        }

Dll函数如下:

extern "C" _declspec(dllexport)int _stdcall count(int init);
int _stdcall count(int init)
{//count 函数,使用参数 init 初始化静态的整形变量 S ,并使 S 自加 1 后返回该值
static int S=init;
S++;
return S;
}
 
下面是调用的代码:

  private void button1_Click_1(object sender, EventArgs e)
        {
            Class1 tryDll = new Class1();
            tryDll.LoadDll(@"D:\Count.dll");//加载dll
            tryDll.LoadFun("_count@4");//找到函数入口 ,这个函数名可能和dll中的不一样,必须找到编绎后的dll函数名,就这个,困扰了我一下午,所以当我找到他时,我快要疯了,郁闷死了
            //tryDll.Invoke("_count@4", typeof(Class1));//错误同上 ,类型必须从委托中派生
            tryDll.UnLoadDll();//缷载dll
    }

 

posted @ 2011-01-23 16:55  orchids  阅读(604)  评论(0)    收藏  举报