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";
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
这里有 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