关闭

MinGW gcc 编译、调用dll

标签: 编译器gccvc
1472人阅读 评论(0) 收藏 举报
分类:

MinGW是Minimalist GNU for Windows, 是在windows平台上做开发的gcc工具集合,支持几乎所有的windows API,几乎可以说是VC的替代,

不过因为GCC原本并不是为windows平台开发的,其主要的目标文件,环境主要是适应Unix和Linux等操作系统,很多在linux下很容易解决的问题,

在windows下却很麻烦。

今天一下午时间都在摆弄MinGW gcc,自己写了一个dll文件并用另一个源文件调用dll中的函数。

一般在VC下很可能使用def文件,但最后很无语的是MinGW连接dll居然什么都没有用,或者是MinGW特性吧。此文把这些过程都记录下来。


环境:

操作系统: Windows 7 sp1 (64 bits),

编译器:MinGW version 4.8.1 (tdm64-2)

先做一个dll,随便编写两个函数即可,当然VC下也可以写一个DllMain ()函数的实现,此处我没有写,只使用了一个关键字__declspec (),一个mydll.h 文件和一个

mydll.c文件:

/*
  author : ez
  date : 2015/7/9
*/

#ifndef _MY_DLL_H
#	define _MY_DLL_H_

#ifdef __cplusplus
extern "C" {
#endif

extern __declspec (dllexport) int add_range (int, int);
extern __declspec (dllexport) double average (int*, int);

#ifdef __cplusplus
}
#endif


#endif // ~_MY_DLL_H_
实现文件mydll.c :

#include "mydll.h"

// __declspec (dllexport) 
int add_range (int _sta, int _end) {
	
	int res = 0;
	if (_sta > _end)
		return 0x7fffffff;
	for (; _sta != _end; _sta ++) {
		res += _sta;
	}
	return res;
	
}

// __declspec (dllexport)
double average (int* _arr, int _cnt) {
	double res = 0.0;
	int i = 0;
	if (_cnt <= 0)
		return (double) (~0);
	for (; i < _cnt; i ++)
		res += _arr [i];
	return (double) (res /= _cnt);
}
之后用gcc编译:

先编译成目标文件:

mingw32-gcc -m32 -c mydll.c

再连接成dll:
mingw32-gcc -m32 -shared - mydll.dll mydll.o

此时即可以得到一个dll文件了,我们可以用HexViewer查看一下是否是合法PE格式文件。

现在来调用这个dll中的函数,我并不想使用它的静态库进行静态编译,只想保留动态链接库,直接由Windows加载器完成所有的调用工作,为此加载器必须知道引用

的dll相关信息,但并不需要在编译期就知道地址都在dll文件的什么偏移量上,可以在运行时动态确定,若不清楚此部分可以查看与PE调用有关的博文。在linux下,如果

使用动态库(linux下一般称为共享库,以so做扩展名的二进制文件,且格式与Windows 的PE完全不同),则直接指定库名称即可,类似以下的命令:

gcc -lpcap -o test  test.c

使用一个 -l 选项即可调用后面指定的库(此例中为libpcap.so,指定库时去掉前面的lib和后面的.so得到库名)。但在windows下这样却行不通,就算把生成的dll前面加上

lib字样,后缀名改为so,也不能用-l 选项指定。后来网上找到很多说要创建一个def文件,VC定义dll时常用的一种文件,文件中列举出了dll导出的所有符号,这样连接器就

可以根据这些信息对dll进行连接,可我却没有找到将def文件输入到GCC的方法,没有类似的选项。而且看到很多博文说将def文件和dll文件通过工具生成a文件,很像windows

下的lib文件,是很多目标文件压缩在一起产生的一种文件。

最终找到的方法确实让我很惊讶,居然简简单单什么都不用做,直接作为输入即可!

以下是调用dll的程序源文件:

/*
  author : ez
  date : 2015/7/9
*/

#include <stdio.h>
#include "mydll.h"

int main (int argc, char* argv []) {
	
	int res = add_range (10, 200);
	printf ("%d\n", res);
	return 0;
}
文件很简单,只调用了add_range (),编译如下:

mingw32-gcc -m32  -o test   test.c  mydll.dll

这样即可!确实很让我无语,“踏破铁鞋无觅处,得来全不费工夫”。


下面把我找到的一些信息也记录一下:

gcc 选项 -Wl:用于给链接器传递参数,

                -soname:指定动态库的soname (Short for object name)

                -output-def = <...> 产生与导出符号相关的def文件

                -out-implib = <*.a> 产生用于提供__img_符号的 .a导入库,即*.a文件


def文件可以使用MinGW 附带的工具pexports生成,输入为dll文件,也可以使用VC附带的工具dumpbin 生成。

MinGW 附带的dlltool 工具可以讲def 文件转化成 *.a文件。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:81988次
    • 积分:1850
    • 等级:
    • 排名:千里之外
    • 原创:96篇
    • 转载:17篇
    • 译文:1篇
    • 评论:115条
    最新评论