动态链结函式库(DLL-Dynamic Linked Library)
2005-02-01 17:12
369 查看
基本上,如果略去VCL软体元件不谈的话,在C++Builder中撰写及使用DLL的方法是和传统Windows SDK是一致的,然而如此一来C++Builder也就失去了它傲人的优势了。因此在本章中我会为你介绍如何撰写使用VCL元件的 DLL,同时也针对各种不同程式发展平台如Visual C++, VB之间的DLL使用上应注意的事项,做一个全面的探讨。
以C++Builder撰写动态链结函式库 (DLL)
图一 以C++Builder撰写的About Dialog
图一所展示的就是我所要撰写的一个以VCL元件组合而成的About Dialog,如何?看起来是不是颇具商业软体架势呢?
C++Builder由於其先天上的优势,因此在视觉化的程式设计领域游刃有馀。然而在现实的工作环境中,也许在你手中的专案并非使用C++Builder来撰写,而是以其他程式工具如Visual C++,VB或是Borland C++完成的,如果要全部改写原来的程式,不仅旷日废时,而且可能老板也不允许,那麽该怎麽办呢?对了,就是利用撰写DLL的途径来达到程式共享的目的,为了要让传统的Windows SDK程式设计人员也可以享受此一优势,因此你可以将部份视觉程式设计部份以DLL完成,然後提供外部函式供他人呼叫,如此你就可以兼顾两者,『执其两端,用於其中』,而顺利地解决问题了。
好了!废话不多说了,现在开始进入正题吧!
建立DLL专案
建立DLL专案的方式和一般应用程式大致相同。同样地你可以由 【File/New】来建立一个新的专案,然後选择DLL类型的专案。
如图二所示:
图二 选择DLL专案类型
建选择完专案类型之後,它就自动为你产生了相关档案。和应用程式不同的是,它只产生了一个Project档,而不包含表格档,而该档案只是一个包含DLL进入点程式的空壳子,程式大致如下:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return 1;
}
DllEntryPoint是DLL内定的程式进入点,因为本程式中并不做任何处理,所以就直接return 1了。
加入TForm表格
为了要撰写如图一的About Dialog,毫无疑问地,我们必须加入一个TForm表格,因为建立DLL专案时,并未自动产生相关的TForm表格,所以你必须以手动方式加入。此时你可以【File/New Form】来加入一个表格。再来我们就可以用和一般应用程式设计相同的方式,加入必要的软体元件,如图叁所示。
图叁 在设计时期(Design Time)的 TForm。
你可以看到,我在程式中使用了叁个TPanel元件(除了标出来的之外,另外还有一个用来作为放置所有元件的平台)。以及一个TImage元件,图叁个的叁个Panel元件的样子都不同,那是利用修改其 BevelInner,BevelOuter,BevelWidth来达成的,你可以试着去修改它,看看能否做出更好的效果。至於TImage是用来做为显示那张雅典娜图形的元件。
在安排好了所有元件的位置之後,我们再设定所有元件的OnClick事件处理函式,让它可以在使用者按下滑鼠时,关掉该交谈窗。这个事件处理函式很简单,只有短短的一行。
void __fastcall TForm1::Image1Click(TObject *Sender)
{
Close();
}
好了,至此我们已完成加入表格的程序。
撰写输出函式(Export Function)
在完成的表格的设计後,再来我们就要撰写输出函式,该外部程式可以利用呼叫该函式的方式显示这个表格。我们的输出函式定义如下:
extern "C" void _stdcall ShowImage(void);
其中 extern "C" 是用来告诉编译器,以C的方式来命名,而不要以C++ 的命名法,因为C++ 的命名法会在函式名称後加上参数型态等装饰字,如此会造成其他程式如VC++,VB等无法使用的困扰。另外 __stdcall是用来表示它使用的参数传入方法。我们在後续单元会针对以上两者做更为深入的介绍。
再来我们来看函式本身,这个函式很简单,只是利用new动态产生一个表格,然後利用ShowModal来显示该表格,ShowModal会一直等到使用者按Click之後才关掉表格,此时我们再以delete指令来释放占用的记忆体。
void _export _stdcall ShowImage(void)
{
Form1 = new TForm1(NULL);
Form1->ShowModal();
delete Form1;
}
在完成以上程式之後,你就可以编译程式。此时C++Builder会产生一个DLL档,以本程式而言,它会产生一个DLLSAMP.DLL档案,而这个就是供外部呼叫的动态链结函式库。
在C++Builder中使用DLL
再来我要告诉你如何使用动态链结函式库。我们以前面所产生的DLL为例。使用DLL有两种方式,分别为明确呼叫及不明确呼叫。
我先说明不明确呼叫的使用方式。不明确呼叫指的是,在程式中并没有一行程式是用来载入DLL,而是利用链结一个记载输入函式的函式库档案(LIB),来进行链结,如此系统会自动将该DLL载入,同时在使用完毕後将其释放,不必由使用者(也就是呼叫它的函式)来进行载入及释放的动作。
首先必须产生一个LIB档,你可以利用C++Builder程式目录内的IMPLIB.EXE来产生该档案,切忌勿使用Visual C++ 的IMPLIB.EXE,因为Microsoft所使用的格式是COFF格式的LIB档,而Borland所使用的格式是OMF格式的LIB档。(同样地,若是你的LIB档是要给Visual C++ 链结用的,那就要使用它所附的IMPLIB.EXE,在使用时不可不察)。因此我们可用以下指令产生DLLSAMP.LIB档。
IMPLIB DLLSAMP.LIB DLLSAMP.DLL
如此你就可以得到供程式链结用DLLSAMP.LIB档了。
接着我们来撰写使用该DLL的范例程式。这个程式相当简单,我只在表格中放置一个Button,然後撰写该Button的OnClick事件处理函式,使其呼叫ShowImage函式即可。
有一点要注意的是,你必须将先前产生的DLLSAMP.LIB加入此专案中,利用 【Project/Add to Project】选择LIB型态档案,即可将其加入。
最後我们就可以链结程式,以下为其执行结果。
图四 执行结果。
函式定义 DLL内的函式名 摘要说明
void DllName01(void) @DllName01$qv 因为是CPP程式码
void _stdcall DllName02(void) @DllName02$qqsv 所以函式名都被修
void _cdecl DllName03(void) @DllName03$qv 饰过。
void _pascal DllName04(void) @DLLNAME04$QV
void _fastcall DllName05(void) @DllName05$qqrv
以上结果是否令你丈二金钢、摸不着头绪。这是因为我们的程式名称若以CPP为延伸名,C++Builder会以C++ 特有的命名方式来为函式命名,这种命名方式会在函式名称後加上其使用参数的性质,如参数类别等。这在C++ 中有一个特别的名称,叫做mangled name,这是一种为了要实作出多载函式所发出的命名规则。(注:在C++ 中Add(int) 和Add(double) 可以同时存在,因此必须在object code区分之)。同时这种命名方式由於各个编译器厂商使用的方式各不相同,因此在撰写DLL时要避免使用之。为了要避开以上问题,我们改以下列的宣告方式:
#define _DLLNAME01_H_
#ifndef DLLNAME
#define EXTERN __declspec(dllimport)
#else
#define EXTERN __declspec(dllexport)
#endif
extern "C" {
EXTERN void DllName011(void);
EXTERN void _stdcall DllName022(void);
EXTERN void _cdecl DllName033(void);
EXTERN void _pascal DllName044(void);
EXTERN void _fastcall DllName055(void);
};
#endif
其中extern "C" {琕琕.}; 是用来告诉编译器使用C的命名方式,不要使用C++ 的mangled name。若是其中只有一个函式时,你可以直接以下列方式宣告之:
extern "C" void __stdcall ShowImage();
现在我们可以检视除去mangled name後的函式名称:
函式定义 DLL内的函式名 摘要说明
void DllName01(void) _DllName01 名称加底线
void _stdcall DllName02(void) DllName02 名称未变
void _cdecl DllName03(void) _DllName03 名称加底线
void _pascal DllName04(void) DLLNAME04 名称大写
void _fastcall DllName05(void) @DllName05 名称加@
以上我们可得知,在未加修饰字时和使用_cdecl修饰字时的名称是一样的。而 _pascal修饰字所产生的函式名则和16位元的标准DLL 函式名相同(这在VC++ 是不被接受的),__fastcall的函式名称则加上 @。
其中在WIN32中使用最多的是 _stdcall修饰字,这也是你要撰写一个可以和其他语言共同使用时所使用的修饰字,其次则为 __cdecl修饰字,这是用来传送不定参数型别的函式如printf、sprintf等使用的。其馀两者几乎在DLL没有机会使用。
结论:
由上可知,在C++Builder中撰写DLL时必须注意以下事项:
使用 __declspec(dllimport)及 __declspec(dllexport)的标准型式。
注意C++ 的函式名称编码(mangled name)。
注意修饰字的使用。除非使用不定参数的函式,否则必使用 __stdcall修饰字。
(4) 不要把 __declspec的使用和 __stdcall混淆了。此二者并没有绝对的相关性。即使是程式老手都可能栽在此处,切记,切记!
怎麽样,在看完了以上的介绍後,是否有晃然大悟的感觉。在了解以上的规则後,今後不论在撰写或是使用DLL时遭遇连结的问题时,应该难不倒你吧!
最後,我们将标准的DLL宣告方式列於後,以加深你的印象:
#ifndef _SHOWIMG_H_
#define _SHOWIMG_H_
#ifndef IMGDLL
#define EXTERN __declspec(dllimport)
#else
#define EXTERN __declspec(dllexport)
#endif
extern "C" EXTERN void __stdcall ShowImage(void);
#endif
语言双雄' C++Builder 和Visual C++ 连结
前面我们已经把关於C++Builder撰写DLL所应注意到的事项介绍完了,现在我们来谈另一个重点 - C++Builder和Visual C++ 的连结。若是你没有使用过Visual C++ 的话,可以将此部份略去。若是你在程式设计时必须使用到Visual C++ 的DLL或是必须提供DLL给VC++ 或是VB使用时,也许会带给你意想不到的收获。
VC++ 使用C++Builder的DLL函式
在Visual C++ 中使用C++Builder的DLL的函式方法和在C++Builder中使用大同小异,唯有几件事情必须要注意。
(一)Visual C++ 的LIB档格式和C++Builder的LIB格式不同,因此你必须重新产生一个 LIB。不过,可惜的是VC++ 在32位元的版本中并未提供IMPLIB.EXE函式(这点一直令许多人百思不解),因此你无法很方便地产生LIB档。解决方法有二:其一是在VC++ 内撰写一个同名称的空的DLL函式,令其产生LIB档,其二则是使用 LoadLibrary、GetProcAddress式的明确呼叫方式。
(二)使用前面提到的标准写法。
C++Builder中使用VC++ 的DLL函式
在C++Builder中使用VC++ 的DLL函式时要注意的是Microsoft在Visual C++ 中使用的特殊命名规则。在VC++ 中命名规则除了前面谈到的几项之外,它还使用了一个特殊的参数命名法,简言之,就是在函数名称後面加上参数的大小,这种命名方法会造成C++Builder,VB,Delphi使用的上的困扰。举例来说
extern "C" _declspec(dllexport) void __stdcall ShowImage(void);
在VC++ 中产生的函式名称为ShowImage@0(其中0表示参数大小),而不是如在C++Builder中产生的ShowImage,这是VC++ 已知的问题,这个问题也造成了很多使用non-VC++ 的使用者的问题,解决之道是在该DLL的DEF档中加上以下的叙述
EXPORTS
ShowImage=ShowImage@0
如此便可以产生正确的函式名了,若是你不想修改DEF档,你也可以在程式中加入以下的连结指引
#pragma comment(linker,"/exports:ShowImage=ShowImage@0")
假设你不确定其正确的名称,可以利用DumpBin或是TDump观察之。
以上是针对VC++ 的程式设计的所作的额外说明。最後我们以一个VC++ 程式呼叫本单元的About Dialog DLL做为结束。
此程式的关键程式码如下:
void CVcusedllApp::OnAppAbout()
{
void (*ShowImage)(void);
HINSTANCE hInst;
hInst = LoadLibrary("DLLSAMP2.DLL");
(FARPROC &)ShowImage=GetProcAddress(hInst,"ShowImage");
ShowImage();
FreeLibrary(hInst);
}
以C++Builder撰写动态链结函式库 (DLL)
图一 以C++Builder撰写的About Dialog
图一所展示的就是我所要撰写的一个以VCL元件组合而成的About Dialog,如何?看起来是不是颇具商业软体架势呢?
C++Builder由於其先天上的优势,因此在视觉化的程式设计领域游刃有馀。然而在现实的工作环境中,也许在你手中的专案并非使用C++Builder来撰写,而是以其他程式工具如Visual C++,VB或是Borland C++完成的,如果要全部改写原来的程式,不仅旷日废时,而且可能老板也不允许,那麽该怎麽办呢?对了,就是利用撰写DLL的途径来达到程式共享的目的,为了要让传统的Windows SDK程式设计人员也可以享受此一优势,因此你可以将部份视觉程式设计部份以DLL完成,然後提供外部函式供他人呼叫,如此你就可以兼顾两者,『执其两端,用於其中』,而顺利地解决问题了。
好了!废话不多说了,现在开始进入正题吧!
建立DLL专案
建立DLL专案的方式和一般应用程式大致相同。同样地你可以由 【File/New】来建立一个新的专案,然後选择DLL类型的专案。
如图二所示:
图二 选择DLL专案类型
建选择完专案类型之後,它就自动为你产生了相关档案。和应用程式不同的是,它只产生了一个Project档,而不包含表格档,而该档案只是一个包含DLL进入点程式的空壳子,程式大致如下:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return 1;
}
DllEntryPoint是DLL内定的程式进入点,因为本程式中并不做任何处理,所以就直接return 1了。
加入TForm表格
为了要撰写如图一的About Dialog,毫无疑问地,我们必须加入一个TForm表格,因为建立DLL专案时,并未自动产生相关的TForm表格,所以你必须以手动方式加入。此时你可以【File/New Form】来加入一个表格。再来我们就可以用和一般应用程式设计相同的方式,加入必要的软体元件,如图叁所示。
图叁 在设计时期(Design Time)的 TForm。
你可以看到,我在程式中使用了叁个TPanel元件(除了标出来的之外,另外还有一个用来作为放置所有元件的平台)。以及一个TImage元件,图叁个的叁个Panel元件的样子都不同,那是利用修改其 BevelInner,BevelOuter,BevelWidth来达成的,你可以试着去修改它,看看能否做出更好的效果。至於TImage是用来做为显示那张雅典娜图形的元件。
在安排好了所有元件的位置之後,我们再设定所有元件的OnClick事件处理函式,让它可以在使用者按下滑鼠时,关掉该交谈窗。这个事件处理函式很简单,只有短短的一行。
void __fastcall TForm1::Image1Click(TObject *Sender)
{
Close();
}
好了,至此我们已完成加入表格的程序。
撰写输出函式(Export Function)
在完成的表格的设计後,再来我们就要撰写输出函式,该外部程式可以利用呼叫该函式的方式显示这个表格。我们的输出函式定义如下:
extern "C" void _stdcall ShowImage(void);
其中 extern "C" 是用来告诉编译器,以C的方式来命名,而不要以C++ 的命名法,因为C++ 的命名法会在函式名称後加上参数型态等装饰字,如此会造成其他程式如VC++,VB等无法使用的困扰。另外 __stdcall是用来表示它使用的参数传入方法。我们在後续单元会针对以上两者做更为深入的介绍。
再来我们来看函式本身,这个函式很简单,只是利用new动态产生一个表格,然後利用ShowModal来显示该表格,ShowModal会一直等到使用者按Click之後才关掉表格,此时我们再以delete指令来释放占用的记忆体。
void _export _stdcall ShowImage(void)
{
Form1 = new TForm1(NULL);
Form1->ShowModal();
delete Form1;
}
在完成以上程式之後,你就可以编译程式。此时C++Builder会产生一个DLL档,以本程式而言,它会产生一个DLLSAMP.DLL档案,而这个就是供外部呼叫的动态链结函式库。
在C++Builder中使用DLL
再来我要告诉你如何使用动态链结函式库。我们以前面所产生的DLL为例。使用DLL有两种方式,分别为明确呼叫及不明确呼叫。
我先说明不明确呼叫的使用方式。不明确呼叫指的是,在程式中并没有一行程式是用来载入DLL,而是利用链结一个记载输入函式的函式库档案(LIB),来进行链结,如此系统会自动将该DLL载入,同时在使用完毕後将其释放,不必由使用者(也就是呼叫它的函式)来进行载入及释放的动作。
首先必须产生一个LIB档,你可以利用C++Builder程式目录内的IMPLIB.EXE来产生该档案,切忌勿使用Visual C++ 的IMPLIB.EXE,因为Microsoft所使用的格式是COFF格式的LIB档,而Borland所使用的格式是OMF格式的LIB档。(同样地,若是你的LIB档是要给Visual C++ 链结用的,那就要使用它所附的IMPLIB.EXE,在使用时不可不察)。因此我们可用以下指令产生DLLSAMP.LIB档。
IMPLIB DLLSAMP.LIB DLLSAMP.DLL
如此你就可以得到供程式链结用DLLSAMP.LIB档了。
接着我们来撰写使用该DLL的范例程式。这个程式相当简单,我只在表格中放置一个Button,然後撰写该Button的OnClick事件处理函式,使其呼叫ShowImage函式即可。
有一点要注意的是,你必须将先前产生的DLLSAMP.LIB加入此专案中,利用 【Project/Add to Project】选择LIB型态档案,即可将其加入。
最後我们就可以链结程式,以下为其执行结果。
图四 执行结果。
函式定义 DLL内的函式名 摘要说明
void DllName01(void) @DllName01$qv 因为是CPP程式码
void _stdcall DllName02(void) @DllName02$qqsv 所以函式名都被修
void _cdecl DllName03(void) @DllName03$qv 饰过。
void _pascal DllName04(void) @DLLNAME04$QV
void _fastcall DllName05(void) @DllName05$qqrv
以上结果是否令你丈二金钢、摸不着头绪。这是因为我们的程式名称若以CPP为延伸名,C++Builder会以C++ 特有的命名方式来为函式命名,这种命名方式会在函式名称後加上其使用参数的性质,如参数类别等。这在C++ 中有一个特别的名称,叫做mangled name,这是一种为了要实作出多载函式所发出的命名规则。(注:在C++ 中Add(int) 和Add(double) 可以同时存在,因此必须在object code区分之)。同时这种命名方式由於各个编译器厂商使用的方式各不相同,因此在撰写DLL时要避免使用之。为了要避开以上问题,我们改以下列的宣告方式:
#define _DLLNAME01_H_
#ifndef DLLNAME
#define EXTERN __declspec(dllimport)
#else
#define EXTERN __declspec(dllexport)
#endif
extern "C" {
EXTERN void DllName011(void);
EXTERN void _stdcall DllName022(void);
EXTERN void _cdecl DllName033(void);
EXTERN void _pascal DllName044(void);
EXTERN void _fastcall DllName055(void);
};
#endif
其中extern "C" {琕琕.}; 是用来告诉编译器使用C的命名方式,不要使用C++ 的mangled name。若是其中只有一个函式时,你可以直接以下列方式宣告之:
extern "C" void __stdcall ShowImage();
现在我们可以检视除去mangled name後的函式名称:
函式定义 DLL内的函式名 摘要说明
void DllName01(void) _DllName01 名称加底线
void _stdcall DllName02(void) DllName02 名称未变
void _cdecl DllName03(void) _DllName03 名称加底线
void _pascal DllName04(void) DLLNAME04 名称大写
void _fastcall DllName05(void) @DllName05 名称加@
以上我们可得知,在未加修饰字时和使用_cdecl修饰字时的名称是一样的。而 _pascal修饰字所产生的函式名则和16位元的标准DLL 函式名相同(这在VC++ 是不被接受的),__fastcall的函式名称则加上 @。
其中在WIN32中使用最多的是 _stdcall修饰字,这也是你要撰写一个可以和其他语言共同使用时所使用的修饰字,其次则为 __cdecl修饰字,这是用来传送不定参数型别的函式如printf、sprintf等使用的。其馀两者几乎在DLL没有机会使用。
结论:
由上可知,在C++Builder中撰写DLL时必须注意以下事项:
使用 __declspec(dllimport)及 __declspec(dllexport)的标准型式。
注意C++ 的函式名称编码(mangled name)。
注意修饰字的使用。除非使用不定参数的函式,否则必使用 __stdcall修饰字。
(4) 不要把 __declspec的使用和 __stdcall混淆了。此二者并没有绝对的相关性。即使是程式老手都可能栽在此处,切记,切记!
怎麽样,在看完了以上的介绍後,是否有晃然大悟的感觉。在了解以上的规则後,今後不论在撰写或是使用DLL时遭遇连结的问题时,应该难不倒你吧!
最後,我们将标准的DLL宣告方式列於後,以加深你的印象:
#ifndef _SHOWIMG_H_
#define _SHOWIMG_H_
#ifndef IMGDLL
#define EXTERN __declspec(dllimport)
#else
#define EXTERN __declspec(dllexport)
#endif
extern "C" EXTERN void __stdcall ShowImage(void);
#endif
语言双雄' C++Builder 和Visual C++ 连结
前面我们已经把关於C++Builder撰写DLL所应注意到的事项介绍完了,现在我们来谈另一个重点 - C++Builder和Visual C++ 的连结。若是你没有使用过Visual C++ 的话,可以将此部份略去。若是你在程式设计时必须使用到Visual C++ 的DLL或是必须提供DLL给VC++ 或是VB使用时,也许会带给你意想不到的收获。
VC++ 使用C++Builder的DLL函式
在Visual C++ 中使用C++Builder的DLL的函式方法和在C++Builder中使用大同小异,唯有几件事情必须要注意。
(一)Visual C++ 的LIB档格式和C++Builder的LIB格式不同,因此你必须重新产生一个 LIB。不过,可惜的是VC++ 在32位元的版本中并未提供IMPLIB.EXE函式(这点一直令许多人百思不解),因此你无法很方便地产生LIB档。解决方法有二:其一是在VC++ 内撰写一个同名称的空的DLL函式,令其产生LIB档,其二则是使用 LoadLibrary、GetProcAddress式的明确呼叫方式。
(二)使用前面提到的标准写法。
C++Builder中使用VC++ 的DLL函式
在C++Builder中使用VC++ 的DLL函式时要注意的是Microsoft在Visual C++ 中使用的特殊命名规则。在VC++ 中命名规则除了前面谈到的几项之外,它还使用了一个特殊的参数命名法,简言之,就是在函数名称後面加上参数的大小,这种命名方法会造成C++Builder,VB,Delphi使用的上的困扰。举例来说
extern "C" _declspec(dllexport) void __stdcall ShowImage(void);
在VC++ 中产生的函式名称为ShowImage@0(其中0表示参数大小),而不是如在C++Builder中产生的ShowImage,这是VC++ 已知的问题,这个问题也造成了很多使用non-VC++ 的使用者的问题,解决之道是在该DLL的DEF档中加上以下的叙述
EXPORTS
ShowImage=ShowImage@0
如此便可以产生正确的函式名了,若是你不想修改DEF档,你也可以在程式中加入以下的连结指引
#pragma comment(linker,"/exports:ShowImage=ShowImage@0")
假设你不确定其正确的名称,可以利用DumpBin或是TDump观察之。
以上是针对VC++ 的程式设计的所作的额外说明。最後我们以一个VC++ 程式呼叫本单元的About Dialog DLL做为结束。
此程式的关键程式码如下:
void CVcusedllApp::OnAppAbout()
{
void (*ShowImage)(void);
HINSTANCE hInst;
hInst = LoadLibrary("DLLSAMP2.DLL");
(FARPROC &)ShowImage=GetProcAddress(hInst,"ShowImage");
ShowImage();
FreeLibrary(hInst);
}
相关文章推荐
- Unable to load dynamic library 'c:/php/extensions/php_mssql.dll'
- php出现Unable to load dynamic library 'c:\php\extensions\php_mssql.dll'
- PHP Startup: Unable to load dynamic library pho_exif.dll
- DLL (Dynamic Link Library)
- Dynamic-Link Library Search Order(dll搜索顺序)
- PHP Warning: PHP Startup: Unable to load dynamic library 'F:\phpWorkspace\php5\ext\php_mysqli.dll'
- PHP Warning Unable to load dynamic library 'E:/lib/php-5.2.17/ext/php_mysqli.dll'
- DLL(Dynamic Linkable Library)
- Dynamic Linking Library(DLL)
- PHP Warning: PHP Startup: Unable to load dynamic library \ D:/php5/ext/php_mysqli.dll\
- 如何解决PHP startup: Unable to load dynamic library的错误(php中的各dll间的相依关系)
- PHP Warning: PHP Startup: Unable to load dynamic library './php_mysql.dll' - /xd5/xd2/xb2/xbb/xb5/xbd/xd6/xb8/xb6/xa8/xb5/xc4/x
- DLL(Dynamic Link Library )
- VC++生成DLL(DynamicLinkLibrary…
- Warning: PHP Startup: Unable to load dynamic library 'php/ext\php_pgsql.dll' - %1 不是有效的 Win32 应用程序
- How to Load a Java Native/Dynamic Library (DLL)
- unable to load dynamic library php_curl.dll
- PHP Warning: PHP Startup: Unable to load dynamic library 'C:/PHP/ext\\php_ldap.dll' - The specified
- wamp在win7-64位下Unable to load dynamic library php_curl.dll
- The procedure entry point XXX could not be located in the dynamic link library XXX.dll