Nginx模块开发 – C++模块

Nginx使用纯C语言开发,默认使用GCC编译,如何使用C++开发Nginx模块或者在开发的Nginx模块中引入C++库呢?

首先介绍下C和C++混合编程的背景知识。

我们知道C++ 是在 C 语言的基础上发展起来的。在某种程度上,我们可将 C++ 看做 C 的一种扩展。在本质上,二者的数据类型和函数调用惯例都是一致的, C 与 C++ 混合编译也是很自然的事情。

二者的区别仅在于编译后函数的名字不同──C 简单地使用函数名而不考虑参数的个数或类型,而 C++ 编译后的函数名则总是将参数类型列表作为其一部分。尽管如此,C++ 提供了特殊的机制来声明 C 函数,这意味着一个 C++ 程序可以直接声明和调用 C 函数。

C++调用C函数

C++调用C实现的函数func_implement_by_c时,在C++代码里的函数声明必须用extern “C” 前缀:

/*
 * file name: cpp_caller.cpp
 */
extern "C" void func_implement_by_c(char *str);
void cpp_caller()
{
    func_implement_by_c("I'm from CPP");
}

int main()
{
    cpp_caller();
}

C调用C++函数

C如果要调用C++的代码,特别是要调用类的成员函数,一般需要把C++函数封装成C样式的函数:

/**
 * file name: c_wapper_of_member_func.cpp
 */
void c_wapper_of_member_func(char *str)
{
    class TestClass;

    TestClass a;

    a.member_func(str);
}

在C中调用时,也是需要在函数声明前加extern “C”前缀:

/**
 * file name: c_caller.c
 */
extern "C" void c_wrapper_of_member_func(char *str);
void c_caller()
{
   c_wrapper_of_member_func("I'm from C");
}

int main()
{
   c_caller();
}

下面我们理一下Nginx C++模块相关解决方案的设计思路。

首先,不要试图用C++编译器(如G++)来编译Nginx的官方代码,这会带来大量的不可控错误。正确的做法是仍然用C编译器来编译Nginx官方提供的各模块,而用C++编译器来编译用C++语言开发的模块,并打包成静态库。然后利用C和C++混合编程的思路,将C++写成的模块封装成C样式的接口来和Nginx的其他模块进行交互。

1. C++模块使用Nginx的头文件,需要使用extern “C” 包起来

#ifdef __cplusplus
extern "C" {
#endif

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <nginx.h>

#ifdef __cplusplus
}
#endif

2. 将C++模块封装成C样式的接口,将模块注册到Nginx中

3. 修改C++模块的配置文件(模块目录下的config文件),实现最终的编译

在CORE_INCS中条件增加头文件路径,在CORE_LIBS中增加库文件的路径,并增加”-lstdc++”链接选项:

比如,我们用C++实现的Nginx模块代码最终打包成静态库libcpp_module.a,则配置文件修改如下:

ngx_feature="http_push_stream_module"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=

CPP_MODULE_DIR="/data/packages/nginx-push-stream-module/cpp-module"

ngx_addon_name=ngx_http_push_stream_module
HTTP_MODULES="$HTTP_MODULES ngx_http_push_stream_module"
CORE_INCS="$CORE_INCS \
    $ngx_addon_dir/src \
    $ngx_addon_dir/include \
    $CPP_MODULE_DIR"
CORE_LIBS="$CORE_LIBS -L$CPP_MODULE_DIR -lstdc++ -lcpp_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
    ${ngx_addon_dir}/src/ngx_http_push_stream_module.c"

have=NGX_HTTP_HEADERS . auto/have
. auto/feature

#if not have sha1 or do not want to use WebSocket comment the lines bellow
USE_SHA1=YES
have=NGX_HAVE_SHA1 . auto/have
此条目发表在Nginx分类目录。将固定链接加入收藏夹。