MinGW .dll .lib 库的编译与实现

Mingw32  dll库到编译,导出导入

这里有 hello.def(符号表) hello.h  hello.c(编译成库) main.c(主程序调用库)

   符号表 hello.def

  LIBRARY libhello                                    //要加载到dll名
  DESCRIPTION "DLL is used by hello"                  //可加可不加,主要是描诉dll的作用
  EXPORTS                                             //导入函数
          PrintHello @0                                //@0 @4  有问题???  看下面的编译def    
          GetString @4


   头文件 hello.h

#ifndef _HELLO_H_
#define _HELLO_H_
#include <stdio.h>
#include <windows.h>

#if defined DLL_EXPORT                                     //宏定义
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif

//DECLDIR void __stdcall PrintHello(void);                    //导出PringHello(),GetString()函数     __stdcall 关键字 根据参数个数从右到左依次入栈
//DECLDIR void* __stdcall GetString(const char *src);
DECLDIR void PrintHello(void);                    
DECLDIR void* GetString(const char *src);
**********************************************************************
http://hi.baidu.com/luosiyong/item/88a97b0e3bd0ee8802ce1b0b

在开发dll的时候,一般不让编译器改变函数名,所以通常是以C方式编译,即加入了extern "C"说明。但是看上面的组合测试结果,__stdcall和__fastcall编译出来的函数名还是和原始的函数名不同。就拿__stdcall来说,它以C编译导出的时候,会在函数前面加入下划线,并在函数后面加入@和参数总大小的字节数。
注意:他需要写的名称是 "_add@8",而不是简单的"add",否则就会出现函数未定义的链接错误。
**********************************************************************

#endif

   库函数hello.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#define NUMBER 100

#define DLL_EXPORT                            //注:宏定义后  代表头文件到函数是导出的
#include "hello.h"

DECLDIR
//void __stdcall PrintHello(void)
void PrintHello(void)
{
  char ptr[] = "Hello world";
  printf("%s\n",ptr);

  return;
}

DECLDIR
//void* __stdcall GetString(const char *src)
void* GetString(const char *src)
{
 char *dest = (char*)malloc(NUMBER);
 memset(dest,0,NUMBER);
// bzero(dest,NUMBER);
 char *temp = dest;

 while(*src != '\0')
    *dest++ = *src++;

 printf("%s\n",temp);

 free(temp);

 return;
}

    主程序main.c
**************************************************
隐式链接
链接到你.lib
文件并将.dll文件置入你的新项目的路径中去

显示链接
难点的加载DLL的方法是有稍微有点复杂的。你将需要函数指针和一些Windows函数。但是,通过
这种载入DLLs的方法,你不需要DLL的.lib或头文件
**************************************************
#include <stdio.h>
#include <windows.h>
#include "hello.h"

//#pragma comment(lib, "libhello.lib")                          //*************隐式链接?????????生成lib库
//__declspec(dllimport)
//extern void __stdcall PrintHello(void);
//__declspec(dllimport)
//extern void* __stdcall GetString(const char *src);

typedef void (*MYHELLO)(void);                          //定义函数指针
typedef void* (*MYSTRING)(const char*);

int main(int argc,char **argv)
{
  const char *string = "This is a test for dll";

#if 1 

  void *hmodule;                                                //*************显式链接 直接加载dll

  MYHELLO pHello;
  MYSTRING gString;
 // const char hdll[] = "libhello.dll";

  hmodule = LoadLibrary("libhello.dll");                        //加载dll模块,返回模块句柄hmodule
  if(hmodule != NULL)
  {
    printf("%s\n","success");
    pHello = (MYHELLO)GetProcAddress(hmodule,"PrintHello ");     // “ PrintHello @0 ”  把PrintHello@0()的地址映射到pHello,同理;  注:@0 @4 这是根据.def符号表导出,这里还有问题???如何去掉@  形成标准C
    gString = (MYSTRING)GetProcAddress(hmodule,"GetString@4");  //"GetString@4";

    if(pHello != NULL && gString != NULL)
    {
      pHello();                                                   //函数到调用
      gString(string);
    }

    FreeLibrary(hmodule);                                         
  }
#endif

//  PrintHello();
//  GetString(string);

  return 0;
}

一。显式链接dll的步骤
 1.先讨论以下符号表,生成符号表有两种方法
   a.如上面:自己编写到一个,但是没有加@(这里不明白),应该可以不加的,但是若是不加,后面符号表的导出就会出问题,注意main.c里的映射函数到函数名
   b.自动导出 #i686-pc-mingw32-gcc -c hello.c
            #i686-pc-mingw32-dlltool -z hello.def --export-all-symbols hello.o
    
; /opt/mxe/usr/bin/i686-pc-mingw32-dlltool -z hello.def --export-all-symbols hello.o
EXPORTS
        GetString@4 @ 1
        PrintHello@0 @ 2

   可以看出自动导出到文件它加上来“@”,所以自己编写到@ 后面到数字是根据这里加到,若数字有误,则编译会报错
 
 2.生成dll文件,libhello.dll
   #i686-pc-mingw32-gcc -shared -g -o libhello.dll hello.o hello.def

 3.编译主程序main.c生成可执行 main.exe  (PE32)
   #i686-pc-mingw32-gcc -o main.exe main.c libhello.dll
 
 4.执行 #wine main.exe

注:extern "C"
  {
    DECLDIR void __stdcall PrintHello(void);
    DECLDIR void* __stdcall GetString(const char *src);
  }

  编译 ERROR  
  root@localhost:/home/xiaot/workspace/Test/Hello/windows# i686-pc-mingw32-gcc -c hello.c
  In file included from hello.c:8:0:
  hello.h:12:8: error: expected identifier or '(' before string constant
所以不能使用extern "C" ???????

二。隐式链接加载.lib库到步骤    main.c红色代码的实现
 1.由于__stdcall关键字到原因,导致符号表生成有“@”符号,去掉之后
   采取自动导出符号  
  #i686-pc-mingw32-dlltool -z hello.def --export-all-symbols hello.o
  “hello.def”

  ; i686-pc-mingw32-dlltool -z hello.def --export-all-symbols hello.o
  EXPORTS
        GetString @ 1
        PrintHello @ 2

 2.从动态库导出.lib文件 libhello.lib
  #i686-pc-mingw32-dlltool -k --dllname libhello.dll --output-lib libhello.lib --def hello.def

 3.编译 生成main.exe
    #i686-pc-mingw32-gcc -o main.exe main.c libhello.lib

 4.执行 #wine main.exe


参看设置选项的意思      #i686-pc-mingw32-dlltool --help


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Mingw是一个基于GCC的开源工具集,可在Windows平台上编译和链接C/C++代码。而DLL(动态链接)是一种将代码以模块化方式组织的文件格式,可供其他程序在运行时共享和调用。因此,如果想要将Mingw生成的DLL文件转换为LIB(静态)文件,可以采取以下步骤: 首先,打开Mingw所在的命令行终端,并导航到DLL文件所在的目录。 然后,使用以下命令将DLL文件转换为DEF(定义)文件: dlltool -D filename.dll -d filename.def -l filename.a 其中,filename.dllDLL文件的名称,filename.def是DEF文件的输出名称,filename.a是LIB文件的输出名称。 接下来,使用以下命令将DEF文件转换为LIB文件: dlltool --def filename.def --dllname filename.dll --output-lib filename.lib 其中,filename.def是上一步生成的DEF文件名称,filename.dllDLL文件的名称,filename.libLIB文件的输出名称。 完成上述步骤后,就能够成功将Mingw生成的DLL文件转换为LIB文件。值得注意的是,转换后的LIB文件仍然是用于静态链接的,而不是将代码以动态链接方式进行共享和调用。 ### 回答2: mingw是一种开源的编程工具,而dlllib则是Windows系统中用于共享和链接的两种动态链接文件的扩展名。 在mingw中,如果我们有一个dll文件,并且我们想要将其转换为lib文件,可以采取以下步骤: 步骤1:打开mingw命令提示符或终端窗口。 步骤2:进入dll所在的文件夹。可以使用cd命令来实现,例如:cd C:\MyDllFolder 步骤3:使用DLLTOOL命令来进行转换。输入以下命令: dlltool -d mydll.def -l mylib.a -k 这里,mydll.def是dll的导出符号定义文件的名称,mylib.a是要生成的lib文件的名称。-k选项告诉dlltool要生成所需文件。 步骤4:等待转换完成。一旦转换完成,你将会在当前文件夹中看到生成的mylib.a文件。 步骤5:将生成的lib文件用于链接。在你的应用程序中,你可以使用生成的lib文件来链接到dll中的函数和符号。 这些是将mingw dll转换为lib的基本步骤。需要注意的是,转换过程中需要确保dll文件和相应的def文件的一致性,以便能够正确生成lib文件。 ### 回答3: 将MinGW的动态链接DLL)转换为静态链接lib)可以通过以下步骤实现。 首先,需要安装MinGW工具链,确保环境变量已正确配置。然后在命令行中使用gcc命令编译源代码生成动态链接,例如使用以下命令: ``` gcc -shared -o mydll.dll mydll.c ``` 这将生成一个名为mydll.dll的动态链接文件。 接下来,我们需要使用gendef命令生成与DLL关联的def文件。在命令行中输入以下命令: ``` gendef mydll.dll ``` 这将生成一个名为mydll.def的def文件。 现在,我们可以使用dlltool命令将def文件转换为lib文件。在命令行中输入以下命令: ``` dlltool -d mydll.def -l mylib.a -D mydll.dll ``` 这将生成一个名为mylib.a的静态链接文件。 最后,将生成的静态链接文件mylib.a与源代码一起使用,通过在项目中链接该文件,即可将动态链接转换为静态链接。 请注意,在进行这些操作之前,确保源代码中没有使用DLL特有的函数或导出函数,否则可能会遇到编译或链接错误。 这是一个简单的示例过程,具体的操作可能因不同的环境和项目而有所不同。在实际操作中,建议参考MinGW的文档或社区资源,以获得更详细的步骤和帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值