DLL Creation in MingW

本文介绍如何在MingW环境下创建动态链接库(DLL)。通过一个简单的“Hello World”示例,详细讲解了DLL的基本概念、创建步骤及如何实现真正的动态加载。此外还涉及了Windows API函数LoadLibrary和GetProcAddress的使用。
 
DLL Creation in MingW
vishnu, Thu, 2004-08-12 23:54
I've always considered DLLs to be esoterically cool stuff - somehow the idea of one program running another makes my imagination run wild. I've now discovered that in many cases DLLs are a bad idea(TM), but for a fledgling programmer, learning how to create a DLL, especially in a free development environment such as MingW would mean an instant familiarity with a lot of development tools, and a lot of the seemingly hidden options of the incredible gcc compiler.
As usual, we're diving in. You should have a copy of mingw handy. Get the MingW installer from the Current branch in the Mingw download page, that sets you off easy. You should also be familiar with IDE-less coding, or should know enough to set up an IDE to work with Mingw, I'm not going to cover that here.
What are DLLs?
First off, what are DLLs? DLLs are dynamically linked libraries. How are they different from static libraries? In static libraries, the linking is done at compile time: all the library functions are combined with the main fragment of program code to create the executable. When the linking is done at runtime, it is called dynamic linking. Since the linking is done at runtime, it is obvious that the operating system will have something to do with it. That is why most DLL implementations are non-portable.
When a compiled executable that references a DLL is loaded, the OS looks into the file and sees that the executable references a set of "imports" from a DLL file. This is simply a situation equivalent to finding that "This program uses the following functions which are contained in this dll". The OS then looks into the particular DLL. The DLL has a corresponding and matching set of export functions that the OS then maps from the functions referenced in the main executable to the functions in the DLL. Thus, when the executable calls a referenced function, the code in the DLL is executed. Viola! Dynamic linking!
Hello DLL!
I'm now going to describe a standard "Hello world" implementation. The code is in three files: hello.c, dll.h and dll.c. The code is listed and explained below:
hello.c
#include <stdio.h>    
#include "dll.h"
 
int main () {
        hello();
        return 0;
}
 
Hello.c is a standard hello world C program except that the hello() function is going to be dynamically linked. The only special thing here is the inclusion of dll.h.
dll.h
#ifdef BUILD_DLL
/* DLL export */
#define EXPORT __declspec(dllexport)
#else
/* EXE import */
#define EXPORT __declspec(dllimport)
#endif
 
EXPORT void hello(void);
DLL.h is where most of the magic happens. It begins with checking the BUILD_DLL macro. We manually set this macro when building so that the macro EXPORT is set to __declspec(dllexport), so that gcc can build the dll. When the OS calls up the dll from the executable, BUILD_DLL is not set and therefore EXPORT is set to __declspec(dllimport) which is a nice set of macro routines to expose our function to the calling scope.
Note that __declspec(dllexport) and __declspec(dllimport) are mingw macros to faciliate DLL creation. They are mapped to their equivalent WinAPI headers.
dll.c
#include
#include "dll.h"
 
EXPORT void hello(void) {
        printf ("Hello/n");
}
This is the actual code of the hello world routine. There should be nothing special here.
Compiling and Linking the files
DLL creation used to be a tiresome process. Recent advances in gcc and mingw engines have meant that it takes only four steps now to create a dll. They are:
  1. Creating the object code for hello.c
 
gcc -c hello.c
  1. Creating the object code for the dll
gcc -c -DBUILD_DLL dll.c
Notice the use of the -D param by which we set the macro BUILD_DLL. It is used for setting export to __declspec(dllexport) so that compilation can take place.
  1. Creating the dll
gcc -shared -o message.dll dll.o -Wl,--out-implib,libmessage.a
The third step requires more explanation.
The -shared parameter is used for creating a shared libaray; in Win platform it is a dll.
-Wl means wait for next message to the linker.
--out-implib is a param to the linker ld which tells it to create an import library which is used by programs which want to link to your dll.
We are ignoring the definitions file which every well-behaved dll should export. If you follow the step above, GCC will automatically create the definition. For most cases, it will work, but if you want to optimize stuff this is the place to look.
  1. Creating the executable
gcc -o hello.exe hello.o message.dll
The fourth step is actually a bit of gcc magick. The actual step is something like this:
gcc -o hello.exe hello.o -L./ -lmessage
The -L param means that the linker checks the ./ path for imports
-lmessage (or -l message) means to search for the message linker name. It extracts this from message.dll
Once you've finished these steps, run the program!
C:/>hello
Hello!
Wait, that's not dynamic!
You're right, that's not *really* dynamic. Of course, you're loading the function at run-time, but what is the purpose of that if you need to reference the dll at compile-time? One of the reasons why a dll is used is to enable a plugin architecture for your program. Other people can write code that your program can use, and you can't really anticipate other people's dlls, and if you are going to recompile your program every time a new dll comes along, then why use dynamic linking at all?
Solve this by using two functions from the Windows API: LoadLibrary() and GetProcAddress(). We modify the codes for the main module like this:
hello.c
#include <windows.h>
#include <stdio.h>    
 
int main () {
       
        /*Typedef the hello function*/
        typedef void (*pfunc)();
       
        /*Windows handle*/
        HANDLE hdll;
       
        /*A pointer to a function*/
        pfunc hello;
       
        /*LoadLibrary*/
        hdll = LoadLibrary("message.dll");
       
        /*GetProcAddress*/
        hello = (pfunc)GetProcAddress(hdll, "hello");
       
        /*Call the function*/
        hello();
        return 0;
}
The code should be self explanatory, there are just some things that you should remember:
  1. Don't forget to include windows.h
  2. The syntax for LoadLibrary is:
handle = LoadLibrary("path to dll file");
handle is <= HINSTANCE_ERROR if there is an error loading the dll.
  1. The syntax for GetProcAddress is:
pointer_to_function = (pointer_to_function_type)GetProcAddress(dll_handle, "resource_name");
We can also use global variables inside the dll that are prefixed with export as a valid resource name, it needn't be a function. That is,
variable = (type)GetProcAddress(dll_handle, "global_variable_name_inside_dll");
is also valid.
  1. For further error info at any step in the process, call GetLastError()
To compile it, don't change a thing for the dlls. For compiling hello.c, a simple...
gcc -o hello.exe hello.c
...would do.
More information
This doesn't solve the problem of implementing a plugin arch, but we can work towards it. One of the ways in which this is done is to reference a function with a unique name from every dll called. For example, a program searches for all dll files beginning with a particular header in the file name and loads it via LoadLibrary. For example, a music program called foobar might look at all dll files which begin with foo. Thus foo_looks.dll will be loaded, while gym.dll won't be. Then inside the dll, it searches for a particular resource say "play", and loads and runs it.
An implementation of the above method, branched off from sortalg, can be found here.
 
内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值