最近在公司作了一套算法---大数据量下求两点间的最短距离。之前是用c++写了个com让前台去(c#)调用,不过是基于C/S的,现在是公司需要将这个算法发布成服务,使得web也可以调用。一开始是考虑使用java调同样的com,这样我就不用做任何修改,但是同事说java调com不稳定。所以就考虑使用apache来发布服务,将算法打包成apache的一个module,于是开始着手研究。
apxs
是一个为Apache HTTP服务器编译和安装扩展模块的工具,用于编译一个或多个源程序或目标代码文件为动态共享对象,使之可以用由mod_so
提供的LoadModule
指令在运行时加载到Apache服务器中。
因此,要使用这个扩展机制,你的平台必须支持DSO特性,而且Apache httpd
必须内建了mod_so
模块。apxs
工具能自动探测是否具备这样的条件,你也可以自己用这个命令手动探测:
$ httpd -l
该命令的输出列表中应该有mod_so
模块。如果所有这些条件均已具备,则可以很容易地借助apxs
安装你自己的DSO模块以扩展Apache服务器的功能:
$ apxs -i -a -c mod_foo.c
gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
ld -Bshareable -o mod_foo.so mod_foo.o
cp mod_foo.so /path/to/apache/modules/mod_foo.so
chmod 755 /path/to/apache/modules/mod_foo.so
[activating module 'foo' in /path/to/apache/etc/httpd.conf]
$ apachectl restart
/path/to/apache/sbin/apachectl restart: httpd not running, trying to start
[Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module
/path/to/apache/sbin/apachectl restart: httpd started
$ _
其中的参数files可以是任何C源程序文件(.c)、目标代码文件(.o)、甚至是一个库(.a)。apxs
工具会根据其后缀自动编译C源程序或者连接目标代码和库。但是,使用预编译的目标代码时,必须保证它们是地址独立代码(PIC),使之能被动态地加载。如果使用GCC编译,则应该使用 -fpic
参数;如果使用其他C编译器,则应该查阅其手册,为apxs
使用相应的编译参数。
自己安装的apache 没有apxs,需要自己安装。下载:http://www.apachelounge.com/download/
#ifdef __cplusplus
extern "C"{
#endif
/* Forward Declarations */
#ifndef __IToolLab_FWD_DEFINED__
#define __IToolLab_FWD_DEFINED__
typedef interface IToolLab IToolLab;
#endif /* __IToolLab_FWD_DEFINED__ */
#ifdef __cplusplus
typedef class ToolLab ToolLab;
#else
typedef struct ToolLab ToolLab;
#endif /* __cplusplus */
#endif /* __ToolLab_FWD_DEFINED__ */
...
EXTERN_C const IID LIBID_PXGISLib;
EXTERN_C const IID IID_IToolLab;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("F12EC292-117C-4C1F-B346-FE2BDB542466")
IToolLab : public IDispatch
{
public:
...
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE DesDecryptEx(
/* [in] */ BSTR bstrInBuffer,
/* [in] */ BSTR bstrLicense,
/* [retval][out] */ BSTR __RPC_FAR *bstrOutBuffer) = 0;
...
};
#else /* C style interface */
typedef struct IToolLabVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
IToolLab __RPC_FAR * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
IToolLab __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
IToolLab __RPC_FAR * This);
...
/* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DesDecryptEx )(
IToolLab __RPC_FAR * This,
/* [in] */ BSTR bstrInBuffer,
/* [in] */ BSTR bstrLicense,
/* [retval][out] */ BSTR __RPC_FAR *bstrOutBuffer);
...
END_INTERFACE
} IToolLabVtbl;
interface IToolLab
{
CONST_VTBL struct IToolLabVtbl __RPC_FAR *lpVtbl;
};
#ifdef COBJMACROS
#define IToolLab_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IToolLab_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IToolLab_Release(This) \
(This)->lpVtbl -> Release(This)
...
#define IToolLab_DesDecryptEx(This,bstrInBuffer,bstrLicense,bstrOutBuffer) \
(This)->lpVtbl -> DesDecryptEx(This,bstrInBuffer,bstrLicense,bstrOutBuffer)
...
#endif /* COBJMACROS */
#endif /* C style interface */
...
/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IToolLab_DesDecryptEx_Proxy(
IToolLab __RPC_FAR * This,
/* [in] */ BSTR bstrInBuffer,
/* [in] */ BSTR bstrLicense,
/* [retval][out] */ BSTR __RPC_FAR *bstrOutBuffer);
void __RPC_STUB IToolLab_DesDecryptEx_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
...
#endif /* __IToolLab_INTERFACE_DEFINED__ */
EXTERN_C const CLSID CLSID_ToolLab;
#ifdef __cplusplus
class DECLSPEC_UUID("103BBE93-8B87-4284-B5B7-1C787C6F68E3")
ToolLab;
#endif
#endif /* __PXGISLib_LIBRARY_DEFINED__ */
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif
h = CoInitialize(NULL);
if (FAILED(h))
{
return -1;
}
h = CoCreateInstance(CLSID_ToolLab,NULL,1,IID_IToolLab,(void **)&lab);
if(FAILED(h))
{
return -1;
}
BSTR res = lab->DesDecryptEx(cipher,L"TJPxdlGisLicense");
lab->Release();
CoUninitialize();
interface IToolLab
{
CONST_VTBL struct IToolLabVtbl __RPC_FAR *lpVtbl;
};
于是,修改代码,下面是写的一个函数的全部代码
//解密
int decrpt_text(char * cipher_text,char **plain_text)
{
IToolLab* lab = NULL;
HRESULT h;
BSTR res,cipher;
size_t len,num;
wchar_t * wct = NULL;
len = strlen(cipher_text)+1;
wct = (wchar_t *)malloc(len*sizeof(wchar_t));
mbstowcs_s(&num,wct,len,cipher_text,_TRUNCATE);
cipher = SysAllocString(wct);
h = CoInitialize(NULL);
if (FAILED(h))
{
return -1;
}
h = CoCreateInstance(&CLSID_ToolLab,NULL,1,&IID_IToolLab,(void **)&lab);
if(FAILED(h))
{
return -1;
}
lab->lpVtbl->DesDecryptEx(lab,cipher,L"TJPxdlGisLicense",&res);
SysFreeString(cipher);
free(wct);
wct = res;
len = wcslen(wct) + 1;
*plain_text = (char*)malloc(len);
wcstombs_s(&num,*plain_text,len,wct,_TRUNCATE);
(*plain_text)[len - 1] = '\0';
lab->lpVtbl->Release(lab);
CoUninitialize();
return 1;
}
编译,还是错误,但是已经不是语法错误。是因为c调用CoInitialize()需要库文件ole32.lib,因为我还用到了SysFreeString()所以还需要库文件oleaut32.lib.重新编译
apxs -c -i -a -Wl,Zi -Wc,/DEBUG -I "头文件所在目录" mod_helloworld.c ole32.lib oleaut32.lib libhttpd.lib
LoadModule
行到httpd.conf
文件中,以激活此模块,或者,如果此行已经存在,则启用之。
-Wc:compiler-flags
libtool --mode=compile
中附加 compiler-flags ,以增加编译器特有的选项。
-Wl:linker-flags
libtool --mode=link
中附加 linker-flags ,以增加连接器特有的选项.