最近看到有同学在问C#如何动态加载C的DLL,所以在这里跟大家分享一下!

本文以VS2013来做开发示例,请知悉!(注C#项目仅设置了Debug解决方案,release一样的更改即可)。

如下图,工程分为3个:

TestDLL是导出库,导出 test_hello 函数作为要被加载的测试DLL;

DynamicLoadDemo 为动态加载C#动态加载DLL的方式;(注:LoadLibrary、GetProcAddress、FreeLibrary)

StaticLoadDemo为为静态加载C#动态加载DLL的方式。(注:DllImport)

TestDLL:源码展示

TestDLL.h

#pragma once

#ifdef TESTDLL_EXPORTS
#define TESTDLL_API  _declspec(dllexport)
#else
#define TESTDLL_API _declspec(dllimport)
#endif



#ifdef __cplusplus
extern "C"{
#endif
	TESTDLL_API int test_hello();
#ifdef __cplusplus
};
#endif

  

TestDLL.cpp

#include "TestDLL.h"

#ifdef __cplusplus
extern "C"{
#endif
	TESTDLL_API int test_hello()
	{
		::MessageBoxA(NULL,"test_hello","msg",0);
		return 1;
	}
#ifdef __cplusplus
};
#endif

  通过以上代码就顺利的导出了函数test_hello。  depends查看如下图

好了下面我们进入正题:

DynamicLoadDemo :

在C++ 中 使用LoadLibrary、GetProcAddress、FreeLibrary三个函数即可实现DLL的动态加载(不清楚的同学请自动MSDN)。

C#动态load也是用的这3个函数实现,但是C#不提供这些函数的引用方式,那么我们自己就加载系统DLL来获得这三个函数的调用方法!

其实使用的方法也就是DllImport。

如下图

下面是测试代码,测试工程很简单只有一个Button,代码如下

      // int test_hello();
        public delegate int test_hello_fn();
        private void load_click(object sender, EventArgs e)
        {
            Int32 hModule = 0;
            int iResult = 0;
            do
            {
                hModule = CDynamicLoadHelper.LoadLibrary("TestDLL.dll");
                if(0 == hModule)
                {
                    iResult = -1;
                    break;
                }
                //
                IntPtr temp_fn = IntPtr.Zero;  
                temp_fn = CDynamicLoadHelper.GetProcAddress(hModule,"test_hello");//get c export fun  test_hello
                if(IntPtr.Zero == temp_fn)
                {
                    iResult = -2;
                    break;
                }
                test_hello_fn fn = (test_hello_fn)Marshal.GetDelegateForFunctionPointer(temp_fn, typeof(test_hello_fn));
                iResult = fn();
            } while (false);
            if(0 != hModule)
            {
                CDynamicLoadHelper.FreeLibrary(hModule);
                hModule = 0;
            }
            MessageBox.Show("test over result is:" + iResult);
        }

StaticLoadDemo:

直接使用C#的DllImport 引入函数,此时Demo提供2中测试方法,一种带异常捕捉,另外一种不带异常捕捉。

load_catch_click(有异常捕捉的)
load_click(无异常捕捉)
    [DllImport("TestDLL.dll", EntryPoint = "test_hello")]
        public static extern Int32 test_hello_fn();
        private void load_catch_click(object sender, EventArgs e)
        {
            int iResult = 0;
            try
            {
                 iResult = test_hello_fn();
            }catch
            {
                iResult = -1;
            }
            MessageBox.Show("test over result is:" + iResult);
        }

        private void load_click(object sender, EventArgs e)
        {
             int   iResult = test_hello_fn();
            MessageBox.Show("test over result is:" + iResult);
        }

 

运行效果如下:

DynamicLoadDemo.exe:

可以看到第一次弹出的test_hello为DLL弹出的对话框,第二个对话框为C#的结果提示框。

StaticLoadDemo.exe

(略)正常情况下运行情况和DynamicLoadDemo.exe一样(如上图),

 

正常情况下DLL都被正常加载到了。我们这里做一个特俗的事情,就是把当前目录的TestDLL.dll 删掉。看运行情况会怎么样?

DynamicLoadDemo.exe反映正常没有异常捕捉也发现DLL 不存在,运行结果在意料之中。(没有跑飞)

 

StaticLoadDemo.exe

有异常捕捉的

没有异常捕捉的

可以看到没有异常捕捉的直接报错了,

 

文章完!那种加载方式还得看大家的选择,本人对C#仅停留于DEMO层次不评价那种方式更优!

 源码包CSDN:http://download.csdn.net/detail/u012251006/9912376

 

posted @ 2017-07-27 12:22  nelolee  阅读(1633)  评论(0编辑  收藏  举报