BCC(Borland C++ Compiler)编译 ISAPI 扩展或者用MinGW也行
来源:互联网 发布:淘宝在哪里交保证金 编辑:程序博客网 时间:2024/06/05 08:56
今天突发神经,要写个ISAPI扩展,找了一下编译器,发现VS 2017的大小>VS 2015 > VS 2013 > VS 2010 > VS 6 & SP6>BCC,于是下了个BCC,很久没用过BCC,不知道它居然升级了,从2000年的Borland C++ 5.5.1升级到了2016年的Embarcadero C++ 7.20,编译器名称也改了。
bcc32.exe -> bcc32c.exe
brcc32.exe -> rc.exe
所以在Code::Blocks里面,Auto-detect不了7.2版本的,只有再下了个5.5的。下载完了,发现忘记怎么写ISAPI了,幸好以前的马甲在CSDN里留了个BCC编译ISAPI的文章,还能baidu到,于是照本宣科,结果却编译不了,经过N次调试,总算成功了,于是总结一下以免备忘,万一以后还要BCC写ISAPI呢。
1,下载Borland C++ Compiler 5.5,解压到D:\Borland\BCC55
2、下载Code::Blocks 16.01,安装完后打开CodeBlocks,先不管默认编译器,进入IDE界面
打开菜单Settings-Compiler...
Selected Compiler选择Borland C++ Compiler (5.5 - 5.82)
Search Directories 选项卡里,Compiler添加D:\Borland\BCC55\Include,Linker添加D:\Borland\BCC55\Lib和D:\Borland\BCC55\Lib\PSDK
Toolchain executables 选项卡里,Compiler's installation directory输入D:\Borland\BCC55
Other settings 选项卡里,点击Advanced options,弹出一个窗口
Commands 选项卡里,Command选择Link object files to dynamic library,Command line macro里将宏改一下,添加一个$def_input变量
原来的宏:$linker -q $libdirs -Tpd $link_options $link_objects,$exe_output,,$libs,,$link_resobjects
改变的宏:$linker -q $libdirs -Tpd $link_options $link_objects,$exe_output,,$libs,$def_input,$link_resobjects
OK - OK,保存设置
3,打开菜单File - New - Project...,选择Shared Library,下一步,选择C,下一步,填写工程名,比如:test,下一步,OK
4,打开main.c,编写代码,其实我是复制微软官网的代码,改了一下, 能编译通过就行
#define WIN32_LEAN_AND_MEAN#include <stdio.h>#include <httpext.h>#ifndef HSE_REQ_SET_FLUSH_FLAG#define HSE_REQ_SET_FLUSH_FLAG (HSE_REQ_END_RESERVED+43)#endifDWORD SendOutputToClient(IN EXTENSION_CONTROL_BLOCK *pecb, IN DWORD msecDelay);DWORD SendOutputToClient(IN EXTENSION_CONTROL_BLOCK *pecb, IN DWORD msecDelay, char *szBuffering) ;BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer){ FILE *fp = fopen("e:\\www\\cgi-bin\\log.txt", "rw"); if (fp) { fprintf(fp, "hello"); fclose(fp); }pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);lstrcpyn((LPSTR) pVer->lpszExtensionDesc, "ISAPI Tester", HSE_MAX_EXT_DLL_NAME_LEN);return TRUE;}DWORD WINAPI HttpExtensionProc(IN EXTENSION_CONTROL_BLOCK *pECB){DWORD hseStatus;DWORD msecDelay;char *pszBuffering;pszBuffering = "default (on)";msecDelay=25;if ( (char)*(pECB->lpszQueryString) != '\0' ){pszBuffering="off"; pECB->ServerSupportFunction (pECB->ConnID,HSE_REQ_SET_FLUSH_FLAG,(LPVOID) TRUE,NULL,NULL);}hseStatus = SendOutputToClient(pECB, msecDelay, pszBuffering);return hseStatus;}BOOL WINAPI TerminateExtension(IN DWORD dwFlags){return TRUE;}DWORD SendHeaderToClient(IN EXTENSION_CONTROL_BLOCK *pecb, IN LPCSTR pszErrorMsg){HSE_SEND_HEADER_EX_INFO SendHeaderExInfo;char szStatus[] = "200 OK";char szHeader[1024];wsprintf(szHeader, "Content-Type: text/plain\r\n\r\n");SendHeaderExInfo.pszStatus = szStatus;SendHeaderExInfo.pszHeader = szHeader;SendHeaderExInfo.cchStatus = lstrlen(szStatus);SendHeaderExInfo.cchHeader = lstrlen(szHeader);SendHeaderExInfo.fKeepConn = FALSE;if (!pecb->ServerSupportFunction(pecb->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &SendHeaderExInfo, NULL, NULL)) return HSE_STATUS_ERROR;return HSE_STATUS_SUCCESS;}DWORD SendOutput(IN EXTENSION_CONTROL_BLOCK *pecb, IN DWORD msecDelay) {CHAR pchOutput[1024];DWORD hseStatus = HSE_STATUS_SUCCESS;int i;DWORD len;for( i=0; i < 10 ; i++ ) {len = wsprintfA(pchOutput, "WriteClient output %d\n", i);if ( !pecb->WriteClient(pecb->ConnID, pchOutput, &len, HSE_IO_SYNC) ){hseStatus = HSE_STATUS_ERROR;break;}Sleep(msecDelay);}return hseStatus;}DWORD SendOutputToClient(IN EXTENSION_CONTROL_BLOCK *pecb, IN DWORD msecDelay, char *szBuffering) {CHAR pchBuffer[1024];DWORD hseStatus = HSE_STATUS_SUCCESS;wsprintfA(pchBuffer, "WriteClient buffering %s", szBuffering);hseStatus = SendHeaderToClient(pecb, pchBuffer);if (hseStatus == HSE_STATUS_SUCCESS) {hseStatus = SendOutput(pecb, msecDelay );if (hseStatus != HSE_STATUS_SUCCESS) {wsprintfA(pchBuffer, "Send Failed: Error (%d)<\br>", GetLastError());SendHeaderToClient(pecb, pchBuffer);}}pecb->ServerSupportFunction( pecb->ConnID, HSE_REQ_DONE_WITH_SESSION, NULL, NULL, NULL);return (hseStatus);}
5,工程根目录下新建test.def文件
LIBRARY "test"EXPORTS GetExtensionVersion HttpExtensionProc TerminateExtension
6,菜单点击Project - Properties...
Build targets 选项卡里,右边大概中间位置的output filename将bin\debug\libtest.dll改为bin\debug\test.dll,然后Release版本的也这样改
左边中下位置,点击Build options,弹出窗口
新窗口的左边列表框里选中工程名,这样debug和release版本都能用同样的编译选项了。
Compiler settings 选项卡里,Compiler flags子选项卡中,Target组里面选中.DLL executable (-tWD)和32-bit multi-threaded (-tWM)
Linker settings 选项卡里,Link libraries里,添加user32,添加kernel32,添加import32,添加cw32mt,cw32mt是静态链接库,cw32mti是动态链接库,需要BCC的dll文件才行,所以我选择了cw32mt,将包含的函数编译进工程里,但这样远远还不够,还需要obj支持
于是other linker options里面,添加
-Gi c0d32.obj
这个是动态链接库支持文件,没有它cw32mt里有两个函数就无法连接,但在工程里如果取消标准库里的一些函数,比如strcpy、strlen,cw32mt就可以不用,但是dll文件会在IIS里奔溃,同时将IIS程序池也搞奔溃掉,我摆渡了很久才找到这个选项
最后,Custom variables选项卡里,添加key = def_input,value = test.def,这样开始在Link object files to dynamic library的宏里面设置的$def_input就有了实例
OK - OK,保存设置
7,Ctrl + F9,工程进行Build,在bin\debug或者bin\release目录下就生成了test.dll,将test.dll放入IIS里设置的可执行目录下,就能运行看到结果了。
——————追加:第二天继续MinGW编译ISAPI的测试——————
因为机器里已经安装了Cygwin和MSYS2,所以首先用Cygwin里的gcc编译项目,gcc版本6.40,编译项目成功,但是用VS的dumpbin -exports dll文件却找不到函数地址
于是使用MSYS2,并在MSYS2模拟器中安装了gcc 7.2,编译 项目成功,同样dumpbin找不到函数地址
dumpbin是VS的dll工具,就是说它能找到地址,那么IIS同样也能找到地址,它找不到IIS也找不到,所以在IIS中,ISAPI扩展会返回500错误
这个问题把我折腾惨了,最后鬼使神差下载了单独版本的MinGW,安装完GCC后,编译项目成功,用dumpbin也能找到函数地址
于是对比了一下,发现GCC线程模式不一样,Cygwin和MSYS2里的gcc都是posix线程,而MinGW里的却是win32线程,所以能用,总算吸取了教训,涨了点姿势。
命令行编译
gcc -c test.cdllwrap --def test.def -o test.dll test.odumpbin -exports test.dll
如果是用CodeBlocks,那么还是要更改一下配置
Settings-Compiler,选择GNU GCC Compiler,Other settings-Advanced options
Commands 选项卡里,Command选择Link object files to dynamic library,Command line macro里将宏改一下,在$exe_output后面添加一个$def_input变量
原宏:$linker -shared -Wl,--output-def=$def_output -Wl,--out-implib=$static_output -Wl,--dll $libdirs $link_objects $link_resobjects -o $exe_output $link_options $libs
现宏:$linker -shared -Wl,--output-def=$def_output -Wl,--out-implib=$static_output -Wl,--dll $libdirs $link_objects $link_resobjects -o $exe_output $def_input $link_options $libs
因为IDE默认是g++最终生成DLL,所以不知为何会带上一个动态链接库,使用dumpbin查看,是一个名为libgcc_s_dw2-1.dll的东东,而且附带两个函数:
25 __deregister_frame_info
6A __register_frame_info
于是Git-bash进入${MINGW_LIB},运行
grep -iaR "__deregister_frame_info" .
最终找到是${MINGW_LIB}/gcc/mingw32/6.3.0/libgcc_eh.a这个文件所持有的函数
于是点击Project - Build options,选中工程名,Linker settings的Other linker options里添加-static-libgcc
重新编译工程,dumpbin发现,libgcc_s_dw2-1.dll不见了,好了,就这样吧,写完手工。
- BCC(Borland C++ Compiler)编译 ISAPI 扩展或者用MinGW也行
- Borland C++ Compiler 5.5 创建ISAPI
- xyssl-0.8或者mbedtls用mingw编译
- gvim+mingw/bcc/msc
- 使用 MinGW 编译 C/C++ 写的 python 扩展
- mingw clang compiler-rt 编译错误
- win7中用MinGW编译x264出现"No working C compiler found."错误
- 用MinGW命令行编译链接c/c++
- minGW 编译.c
- mingw编译segmenter.c
- [编译配置]用MinGW编译C语言的批处理
- 用Borland C++编译uCOS2
- Borland C++Builder 编译ACE经验
- 如何用mingw编译python扩展
- 使用MinGW 编译python扩展模块
- 用MinGW编译ffmpeg
- 用MinGW编译Boost
- 用MinGW编译openssl
- 基于zookeeper的solrCloud集群搭建
- No.1 Mybatis 初次见面
- 问题:什么是变量?变量有什么用?
- 深度学习:CNN RNN DNN 区别 卷积层或是LSTM单元
- 表单json字符串生成
- BCC(Borland C++ Compiler)编译 ISAPI 扩展或者用MinGW也行
- 基础练习 闰年判断
- python pandas 查看数据的前五行
- The Elements of Computing Systems阅读笔记(5)
- s3c2440 ARM9 裸机驱动第三篇—定时器
- React ES6与ES5写法的区别
- SpringBoot依赖及其作用
- ubuntu修改系统/文件夹语言(中文/英文互转)
- 通过java反射机制操作对象的属性方法