Nebula2探秘10-Signal System

Nebula2探秘10-Signal System

happykevins文     

使用Nebula2信号系统的目的:

  Nebula2的信号系统主要功能是对象间的消息传递。
  由于消息的发出者和接收者是在运行时动态邦定的,所以用这种方式传递消息并不会增加程序的耦合度。
  另外Nebula2还提供了一个SignalServer用于实现延时消息。

Nebula2信号系统主要包含以下几个类:
  nSignal:
   继承自nCmdProto类,用于标识一个信号,并描述信号回调函数的原形
  nSignalRegistry:
   包含多个nSignal的集合;nClass继承自此类;因此可以推测出信号是与类
   邦定的,要使Nebula类型支持产生信号,我们首先要向该类注册信号
  nSignalBinding:
   封装了信号接收者及其回调函数,用于向信号发出者注册
  nSignalBindingSet:
   包含多个nSignalBinding的集合
  nSignalEmitter:
   信号发生器,nObject继承自此类;因此所有的Nebula对象都支持发出信号
   的功能,前提是你注册了信号
  nSignalServer:
   这其实是独立于信号系统的一个附加功能,主要是实现了相应延时信号

Nebula2信号系统的使用方法:

  Nebula2的信号系统支持Native代码和脚本两种途径的传递,下面简单介绍通过脚本途径的使用。
  首先需要实现一个用于产生信号的Emtter类,Emitter就是一个普通的继承自nObject的Nebula2类型,只是在初始化命令的函数中添加了信号(nSignal)。
  然后我们需要实现一个Receiver类,Receiver类也是一个继承自nObject的普通Nebula2脚本类,可以将Receiver的脚本指令向Emitter中感兴趣的信号注册,这样在Emitter产生信号时就会向注册的Receiver广播消息了;需要注意的是在Receiver向Emitter注册时需要保证Receiver的回调函数与Emitter的信号的函数原形保持一致。

 Nebula2引擎的Bug:
  需要改正一个Nebula2的Bug,在nargs.h的第276行加上代码:
   this->type = Type::String;
  原来的代码由于缺少这句话,在nArgs从va_list复制String类型参数时会丢失类型信息,所以在信号传递过程中如果使用String类型参数的话Nebula2就会出错。

 下面是Emitter的代码:

/* ************************************************************************** */
/*     Nebula2 - Tutorial 10                                                     */
/*   Nebula2 Signal System                                                     */
/*   author: happykevins                                                         */
/* ************************************************************************** */

///  Emitter.h
#pragma  once
#include 
" kernel/nroot.h "
#include 
" signals/nsignal.h "

class  Emitter :  public  nRoot
{
    
///  @note
    
///  为了支持信号系统,在类的实现中不需要添加任何代码
    
///  只需在Emitter对应的nClass中注册信号即可
    
///  注册信号的工作一般在初始化脚本指令的函数(n_initcmds)中完成
};

///  Emitter.cpp
#include  " Emitter.h "
#include 
" kernel/nkernelserver.h "
#include 
" ../NebulaUtils/nutildefs.h "

nNebulaScriptModule(Emitter, emitter, 
" nroot " );

void  nNebulaScriptInitCmds(emitter)(nClass *  cls)
{
    
///  在这里添加信号
    
///  注册信号始需要指出信号对应回调函数的原形以及信号的ID
    cls -> BeginSignals( 1 );
    cls
-> AddSignal( " v_sig1_s " ' SIG1 ' );
    cls
-> EndSignals();
}

下面是Receiver的代码:

/* ************************************************************************** */
/*     Nebula2 - Tutorial 10                                                     */
/*   Nebula2 Signal System                                                     */
/*   author: happykevins                                                         */
/* ************************************************************************** */

///  Receiver.h
#pragma  once
#include 
" kernel/nroot.h "

class  Receiver:  public  nRoot
{
public :
    
void  Print( const   char *  str)
    {
        n_printf(
" %s " , str);
    }
};

///  Receiver.cpp
#include  " Receiver.h "
#include 
" kernel/nkernelserver.h "
#include 
" ../NebulaUtils/nutildefs.h "

nNebulaScriptModule(Receiver, receiver, 
" nroot " );

static   void  n_print( void *  o, nCmd *  cmd);

void  nNebulaScriptInitCmds(receiver)(nClass *  cl)
{
    
///  为Emitter的回调添加脚本函数
    
///  信号系统也是通过脚本函数来传递消息
    
///  脚本函数的需要与Emitter对应的信号保持一致
    cl -> BeginCmds();
    cl
-> AddCmd( " v_print_s " ' PRNT ' , n_print);
    cl
-> EndCmds();
}

static   void  n_print( void *  o, nCmd *  cmd)
{
    Receiver
*  slf  =  (Receiver * )o;
    slf
-> Print(cmd -> In() -> GetS());
}

下面是使用信号系统的范例代码:

/* ************************************************************************** */
/*     Nebula2 - Tutorial 10                                                     */
/*   Nebula2 Signal System                                                     */
/*   author: happykevins                                                         */
/* ************************************************************************** */

/// ----------------------------------------------------------------------------
///  +必要头文件

//  nebula2 includes
#include  " kernel/nkernelserver.h "
#include 
" kernel/ntimeserver.h "
#include 
" signals/nsignalserver.h "
#include 
" ../NebulaUtils/nutildefs.h "

#include 
" Emitter.h "
#include 
" Receiver.h "

///  -必要头文件
/// ----------------------------------------------------------------------------



/// ----------------------------------------------------------------------------
///  +声明使用的Nebula2 Package&Module
nNebulaUseModule(emitter);
nNebulaUseModule(receiver);
///  -声明使用的Nebula2 Package&Module
/// ----------------------------------------------------------------------------

/// ----------------------------------------------------------------------------
///  +Application
int  main( int  argc,  const   char **  argv)
{
    
///  创建KernelServer
    nKernelServer *  ks  =  n_new(nKernelServer);

    nNebulaAddModule(emitter);
    nNebulaAddModule(receiver);

    
///  创建SignalServer
    nSignalServer *  signals  =  (nSignalServer * )ks -> New( " nsignalserver " " /sys/servers/signals " );

    
///  创建信号发生器
    Emitter *  emit  =  (Emitter * )ks -> New( " emitter " " /usr/signals/emitter " );
    
///  创建信号接收器
    Receiver *  rec  =  (Receiver * )ks -> New( " receiver " " /usr/signals/receiver " );

    
///  将信号接收器邦定到信号发生器指定的信号
    emit -> BindSignal( ' SIG1 ' , rec,  ' PRNT ' 0 true );

    
///  发出立即信号
    emit -> EmitSignal( ' SIG1 ' " Emit Signal Synchronized! " );

    
///  发出延迟信号(5秒后执行)
    emit -> PostSignal( 5.0f ' SIG1 ' " Emit Signal Asynchronized! " );

    n_printf(
" *****Wait Asynchronized Signal***** " );
    
    
///  等待延迟信号
     double  time  =   0 ;
    
while  ( time  <=   8.0f )
    {
        signals
-> Trigger(nTimeServer::Instance() -> GetFrameTime());
        n_sleep(
0.2f );
        time 
+=   0.2f ;
    }

    n_printf(
" *****Press Any Key!***** " );

    
///  销毁KernelServer
    n_delete(ks);

    getchar();
    
return   0 ;
}
///  -Application
/// ----------------------------------------------------------------------------

<The End>

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1350203


你可能感兴趣的:(System)