转自http://blog.csdn.net/akirya/archive/2008/02/14/2093031.aspx
__declspec(dllexport)是告诉编译器用来导出函数的,在代码中不另作说明了 extern "C"的意思就是用C的方式来导出函数,为什么要用C的方式来导出呢. 因为C++中有重载,编译器会对函数名进行更改,修饰成唯一的函数名. __stdcall告诉编译器函数调用方式.这点可以参考其他文章, 我预计也会在blog中写上一篇关于函数调用方式. C++编写的DLL
extern
"
C
"
__declspec(dllexport)
int
Max(
int
x,
int
y)
...
{ return x>y?x:y; }
__declspec(dllexport)
int
__stdcall Min(
int
x,
int
y)
...
{ return x<y?x:y; }
__declspec(dllexport)
double
Min(
double
x,
double
y)
...
{ return x<y?x:y; }
#define
DLLEXPORT extern "C" __declspec(dllexport)
DLLEXPORT
int
swap(
int
*
x,
int
&
y)
...
{ int z = *x; *x = y ; y = z; return 0; }
/**/
/* 这和前面的例子重复了,主要用于调用的例子 */
DLLEXPORT
double
__stdcall Max_d(
double
x,
double
y)
...
{ return x>y?x:y; }
#include
<
string
.h
>
struct
testStruct
...
{ char a; int b; double c; char sz[5]; }
; DLLEXPORT
int
__stdcall UseStruct(testStruct
*
p)
...
{ p->a = 'a'; p->b = 20; p->c = 1.234; strcpy( p->sz , "abcd" ); return sizeof(testStruct); }
/**/
/*这是修改了内存对齐的结构体使用,主要在调用的时候有区别*/
#pragma
pack(push)
#pragma
pack( 1 )
struct
testStruct2
...
{ char a; int b; double c; char sz[5]; }
;
#pragma
pack(pop)
DLLEXPORT
int
__stdcall UseStruct2(testStruct2
*
p)
...
{ p->a = 'a'; p->b = 20; p->c = 1.234; strcpy( p->sz , "abcd" ); return sizeof(testStruct2); }
DLLEXPORT
int
__stdcall UserCallBackFunc(
const
char
*
lp,
int
(__stdcall
*
p)(
const
char
*
) )
...
{ return p( lp ); }
#ifdef __cplusplus
extern
"
C
"
__declspec(dllimport)
int
Max(
int
x,
int
y);
int
__stdcall Min(
int
x,
int
y);
double
Min(
double
x,
double
y);
#else
__declspec(dllimport)
int
Max(
int
x,
int
y);
#endif
#ifdef __cplusplus # define DLLIMPORT
extern
"
C
"
__declspec(dllimport)
#else
# define DLLIMPORT __declspec(dllimport)
#endif
DLLIMPORT
int
swap(
int
*
x,
int
*
y); DLLIMPORT
double
__stdcall Max_d(
double
x,
double
y); #include
<
string
.h
>
typedef
struct
__testStruct
...
{ char a; int b; double c; char sz[5]; }
testStruct; DLLIMPORT
int
__stdcall UseStruct(testStruct
*
p);
#pragma pack(push) #pragma pack( 1 )
typedef
struct
__testStruct2
...
{ char a; int b; double c; char sz[5]; }
testStruct2;
#pragma pack(pop)
DLLIMPORT
int
__stdcall UseStruct2(testStruct2
*
p); DLLIMPORT
int
__stdcall UserCallBackFunc(
const
char
*
lp,
int
(__stdcall
*
p)(
const
char
*
) ); #include
<
stdio.h
>
#pragma
comment(lib,"dlltest.lib")
#include
<
windows.h
>
int
__stdcall CallBackFunc(
const
char
*
lp)
...
{ return printf("%s ",lp); }
int
main()
...
{ int x=2,y=3; testStruct s1; testStruct2 s2; #ifdef __cplusplus printf("%d ",Min( 2,3 ) ); printf("%f ",Min( 2.0,3.0 ) ); #else int(__stdcall *pMin)(int,int)=0; double(*pMin_d)(double,double)=0; HMODULE hDll = GetModuleHandle("dlltest.dll"); pMin_d = (double(*)(double,double)) GetProcAddress( hDll , "?Min@@YANNN@Z" ); if( pMin_d ) printf("%f ",pMin_d(3.0,5.0 ) ); pMin = (int(__stdcall*)(int,int)) GetProcAddress( hDll , "?Min@@YGHHH@Z" ); if( pMin ) printf("%d ",pMin( 3 , 5 ) ); #endif swap( &x,&y ); printf("swap = %d,%d ",x,y); printf( "%d " , Max( 2,4 ) ); printf( "%f " , Max_d( 2.0,4.0 ) ); UseStruct(&s1); UseStruct2( &s2 ); printf( "%c,%d,%f,%s ",s1.a,s1.b,s1.c,s1.sz); printf( "%c,%d,%f,%s ",s2.a,s2.b,s2.c,s2.sz); UserCallBackFunc("abcdef",CallBackFunc); return 0; }
;
program test;
...
{$APPtype CONSOLE}
uses SysUtils,Classes,Math,Windows; type testStruct
=
record a:Char; b:Integer; c:Double; sz:array[
0
..
4
] of
char
; end;
...
{$A1}
...
{定义record使之和 修改了对齐的结构体有相同的内存布局 }
testStruct2
=
record a:Char; b:Integer; c:Double; sz:array[
0
..
4
] of
char
; end;
...
{$A8}
CallBackFunc type
=
function(x:PChar):Integer;stdcall; function Max( x:Integer;y:Integer ):Integer;cdecl;external
'
dlltest.dll
'
name
'
Max
'
; function Max_d( x:Double;y:Double):Double ;stdcall;external
'
dlltest.dll
'
name
'
Max_d
'
; function swap(var x:Integer;var y:Integer):Integer;stdcall;external
'
dlltest.dll
'
name
'
swap
'
; function UseStruct(var x:testStruct):Integer;stdcall;external
'
dlltest.dll
'
name
'
UseStruct
'
; function UseStruct2(var x:testStruct2):Integer;stdcall;external
'
dlltest.dll
'
name
'
UseStruct2
'
; function UserCallBackFunc( lp:PChar ; F:CallBackFunctype ):Integer;stdcall;external
'
dlltest.dll
'
name
'
UserCallBackFunc
'
; function CallFunc(lp:PChar):Integer;stdcall; begin writeln(
'
CallFunc=
'
, lp ); result :
=
0
; end;
...
{ 这里是使用重载函数 }
function Min(x:Integer;y:Integer):Integer;stdcall;external
'
dlltest.dll
'
name
'
?Min@@YGHHH@Z
'
; function Min_d(x:Double;y:Double):Double;cdecl;external
'
dlltest.dll
'
name
'
?Min@@YANNN@Z
'
; procedure test_overland; begin writeln(
'
Min(1,2)=
'
, Min(
1
,
2
) ); writeln(
'
Min_d(1.0,2.1)=
'
, Min_d(
1.0
,
2.1
) ); end; var x,y:Integer; a_struct:testStruct; b_struct:testStruct2; begin writeln(
'
Max(1,2)=
'
, Max(
1
,
2
) ); writeln(
'
Max(1.0,2.0)=
'
, Max_d(
1.0
,
2.0
) ); writeln(
'
x=1,y=2
'
); x :
=
1
;y :
=
2
; swap( x, y); writeln(
'
swap(x,y)=
'
, x ,
'
'
, y ); writeln(
'
UseStruct( a_struct ) result=
'
, UseStruct( a_struct ) ,
'
,sizeof=
'
,
sizeof
(a_struct) ); writeln(
'
UseStruct=
'
, a_struct.a,
'
'
, a_struct.b,
'
'
, a_struct.c ,
'
'
,a_struct.sz ); writeln(
'
UseStruct2( b_struct ) result=
'
, UseStruct2( b_struct ) ,
'
,sizeof=
'
,
sizeof
(b_struct) ); writeln(
'
UseStruct2=
'
, b_struct.a,
'
'
, b_struct.b,
'
'
, b_struct.c ,
'
'
,b_struct.sz ); UserCallBackFunc( PChar(
'
abcdef
'
) , CallFunc ); test_overland; readln; end.
Public
Declare
Sub CopyMemory()
Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) Public Declare Function lstrlen()Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long Public Type testStruct a As Byte b As Long c As Double sz As String * 5 End Type Public Type Temp sz As String * 5 End Type Public Declare Function Max_d()Function Max_d Lib "dlltest" (ByVal a As Double, ByVal b As Double) As Double Public Declare Function Min()Function Min Lib "dlltest" Alias "?Min@@YGHHH@Z" (ByVal a As Long, ByVal b As Long) As Long Public Declare Function UseStruct()Function UseStruct Lib "dlltest" (ByRef a As testStruct) As Long Public Declare Function UseStruct2()Function UseStruct2 Lib "dlltest" (ByRef a As Any) As Long Public Declare Function UserCallBackFunc()Function UserCallBackFunc Lib "dlltest" (ByVal s As String, ByVal f As Long) As Long Function CallBack()Function CallBack(ByVal lp As Long) As Long Dim L As Long L = lstrlen(lp) Dim s As String s = String$(L + 1, vbNullChar) CopyMemory s, lp, L MsgBox s & " , " & Str$(L) Debug.Print "CallBack", s CallBack = 3 End Function Sub Main()Sub Main() Debug.Print Max_d(4, 5), Min(4, 6) Dim a As testStruct Debug.Print UseStruct(a) Debug.Print Chr(a.a), a.b, a.c, a.sz Dim buf(18) As Byte Debug.Print "----------------" Debug.Print UseStruct2(buf(0)) Dim t As Byte CopyMemory t, buf(0), 1 Dim L As Long CopyMemory L, buf(1), 4 Dim d As Double CopyMemory d, buf(5), 8 Dim s As Temp CopyMemory s, buf(13), 5 Debug.Print Chr(t), L, d, s.sz Debug.Print UserCallBackFunc("_测试asdasd中文sdfasdf", AddressOf CallBack) End Sub
library dlltest; uses SysUtils, Classes; function Max(X, Y: Integer): Integer; cdecl; begin
if
X
>
Y then Max :
=
X
else
Max :
=
Y; end; function Min(X, Y: Integer): Integer;overload; stdcall; begin
if
X
<
Y then Min :
=
X
else
Min :
=
Y; end; function Min(X, Y: Double): Double;overload; cdecl; begin
if
X
<
Y then Min :
=
X
else
Min :
=
Y; end; function swap( var x: Integer; var y: Integer): Integer; cdecl; var z:integer; begin z :
=
x; x :
=
y; y :
=
z; result :
=
1
; end; function Max_d(X, Y:Double):Double;stdcall; begin
if
X
>
Y then Max_d :
=
X
else
Max_d :
=
Y; end; type testStruct
=
record a:Char; b: Integer; c:Double; sz: array[
0
..
4
] of
char
; end; function UseStruct( var x:testStruct): Integer;stdcall; begin x.a :
=
'
a
'
; x.b :
=
20
; x.c :
=
1.234
; StrCopy( x.sz , PChar(
'
abcd
'
) ); UseStruct:
=
SizeOf(testStruct) ; end; {$A1} type testStruct2
=
record a:Char; b: Integer; c:Double; sz: array[
0
..
4
] of
char
; end; {$A8} function UseStruct2( var x:testStruct2): Integer;stdcall; begin x.a :
=
'
a
'
; x.b :
=
20
; x.c :
=
1.234
; StrCopy( x.sz , PChar(
'
abcd
'
) ); UseStruct2 :
=
SizeOf(testStruct2) ; end; type CallBackFuncType
=
function(x:PChar): Integer;stdcall; function UserCallBackFunc( lp:PChar ; F:CallBackFuncType ): Integer;stdcall; begin F( lp ); UserCallBackFunc:
=
StrLen( lp ) ; end; exports Max, Min(X, Y: Integer) name
'
?Min@@YGHHH@Z
'
,
//
和C++导出的重载函数名字一样
Min(X, Y: Double)name
'
?Min@@YANNN@Z
'
, swap, Max_d, UseStruct, UseStruct2, UserCallBackFunc; begin end.